Dart equivalent to Python zip and list comprehension for generating list of widgets from two lists
Question:
I want to create a list of widgets MyWidget(categoryName, color)
from the following two lists.
static const _categoryNames = <String>[
'Length',
'Area',
'Volume',
];
static const _baseColors = <Color>[
Colors.teal,
Colors.orange,
Colors.pinkAccent,
];
In Python I would use a list comprehension with zip to get the result.
my_widget_list = [MyWidget(categoryName, baseColor) for categoryName, baseColor in zip(_categoryNames, _baseColors)]
Googling for a similar method for Dart did not provide any satisfactory solution.
Answers:
There is a zip
function from package:quiver
. Combined with collection-for (Dart’s equivalent to Python list comprehensions) can get you most of the way there. Dart does not have Python’s automatic unpacking, so unfortunately you won’t get nice variable names:
my_widget_list = [
for (var pair in zip([_categoryNames, _baseColors]))
MyWidget(pair[0], pair[1]),
]
If your aim is to create a list of widgets (assuming both your lists will have same number of elements). You can try
List<Widget> getWidgets() {
List<Widget> my_widget_list = [];
const _categoryNames = <String>[
'Length',
'Area',
'Volume',
];
const _baseColors = <Color>[
Colors.teal,
Colors.orange,
Colors.pinkAccent,
];
for (int i = 0; i <= _categoryNames.length -1 ; i++){
my_widget_list.add(MyWidget(_categoryNames[i],_baseColors[i]));
}
return my_widget_list;
}
Widget MyWidget(String categoryName, Color baseColor){
return Container(
color: baseColor,
child: Text(categoryName,));
}
"Pythonic" Dart Syntax
You can do something that looks very similar to Python using Control Flow Collections.
List<Widget> myWidgetList = [
for (String name in categoryNames)
for (Color color in baseColors)
if (baseColors.indexOf(color) == categoryNames.indexOf(name))
myWidget(name, color)
];
Maybe a little less "Pythonic" but more concise . . .
List<Widget> myWidgetList = [
for (String name in categoryNames)
myWidget(name, baseColors[categoryNames.indexOf(name)])
];
Specifically, you should read over Control Flow Collections: Composing
Complete Unit Test
For you convenience here is a quick unit-test you can run.
import 'dart:core';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
test('build list of widgets with composing', () {
List<Widget> myWidgetList = [
for (String name in categoryNames)
for (Color color in baseColors)
if (baseColors.indexOf(color) == categoryNames.indexOf(name))
myWidget(name, color)
];
List<Widget> myOtherWidgetList = [
for (String name in categoryNames)
myWidget(name, baseColors[categoryNames.indexOf(name)])
];
expect(myWidgetList.length, equals(myOtherWidgetList.length));
expect(myWidgetList.toString(), equals(myOtherWidgetList.toString()));
print(myWidgetList);
});
}
const categoryNames = <String>[
'Length',
'Area',
'Volume',
];
const baseColors = <Color>[
Colors.teal,
Colors.orange,
Colors.pinkAccent,
];
Widget myWidget(String categoryName, Color baseColor) {
return Container(
color: baseColor,
child: Text(
categoryName,
));
}
Try use IterableZip of dart collection/collection: https://pub.dev/documentation/collection/latest/collection/IterableZip-class.html
I want to create a list of widgets MyWidget(categoryName, color)
from the following two lists.
static const _categoryNames = <String>[
'Length',
'Area',
'Volume',
];
static const _baseColors = <Color>[
Colors.teal,
Colors.orange,
Colors.pinkAccent,
];
In Python I would use a list comprehension with zip to get the result.
my_widget_list = [MyWidget(categoryName, baseColor) for categoryName, baseColor in zip(_categoryNames, _baseColors)]
Googling for a similar method for Dart did not provide any satisfactory solution.
There is a zip
function from package:quiver
. Combined with collection-for (Dart’s equivalent to Python list comprehensions) can get you most of the way there. Dart does not have Python’s automatic unpacking, so unfortunately you won’t get nice variable names:
my_widget_list = [
for (var pair in zip([_categoryNames, _baseColors]))
MyWidget(pair[0], pair[1]),
]
If your aim is to create a list of widgets (assuming both your lists will have same number of elements). You can try
List<Widget> getWidgets() {
List<Widget> my_widget_list = [];
const _categoryNames = <String>[
'Length',
'Area',
'Volume',
];
const _baseColors = <Color>[
Colors.teal,
Colors.orange,
Colors.pinkAccent,
];
for (int i = 0; i <= _categoryNames.length -1 ; i++){
my_widget_list.add(MyWidget(_categoryNames[i],_baseColors[i]));
}
return my_widget_list;
}
Widget MyWidget(String categoryName, Color baseColor){
return Container(
color: baseColor,
child: Text(categoryName,));
}
"Pythonic" Dart Syntax
You can do something that looks very similar to Python using Control Flow Collections.
List<Widget> myWidgetList = [
for (String name in categoryNames)
for (Color color in baseColors)
if (baseColors.indexOf(color) == categoryNames.indexOf(name))
myWidget(name, color)
];
Maybe a little less "Pythonic" but more concise . . .
List<Widget> myWidgetList = [
for (String name in categoryNames)
myWidget(name, baseColors[categoryNames.indexOf(name)])
];
Specifically, you should read over Control Flow Collections: Composing
Complete Unit Test
For you convenience here is a quick unit-test you can run.
import 'dart:core';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
test('build list of widgets with composing', () {
List<Widget> myWidgetList = [
for (String name in categoryNames)
for (Color color in baseColors)
if (baseColors.indexOf(color) == categoryNames.indexOf(name))
myWidget(name, color)
];
List<Widget> myOtherWidgetList = [
for (String name in categoryNames)
myWidget(name, baseColors[categoryNames.indexOf(name)])
];
expect(myWidgetList.length, equals(myOtherWidgetList.length));
expect(myWidgetList.toString(), equals(myOtherWidgetList.toString()));
print(myWidgetList);
});
}
const categoryNames = <String>[
'Length',
'Area',
'Volume',
];
const baseColors = <Color>[
Colors.teal,
Colors.orange,
Colors.pinkAccent,
];
Widget myWidget(String categoryName, Color baseColor) {
return Container(
color: baseColor,
child: Text(
categoryName,
));
}
Try use IterableZip of dart collection/collection: https://pub.dev/documentation/collection/latest/collection/IterableZip-class.html