I have a 2-d list, I am adding data using `
quotationList.add( [productName.text, double.parse(productPrice.text), _n] );`
output is:
[[qwe, 555.0, 1], [qwe 1, 5555.0, 2]]
now i want to add this 2-d list into my products list, i can't figure out how to do that?
my products list looks like this, with static data
final products = <Product>[
Product('1', "random text", 3.99, 2),
Product('2', "random text", 15, 2),
Product('3', "random text", 6.95, 3),
Product('4', "random text", 49.99, 4),
];
i want to make make it dynamic using some loops or something, like this
final products = <Product>[
for(int i=0; i<quotationList.length; i++)
{
Product(i.toString(), quotationList[i][0], quotationList[i][1], quotationList[i][2]),
}
];
but i got this error
The element type 'Set<Product>' can't be assigned to the list type 'Product'.
The issue is the {} braces for the for loop inside the list.
Change it to:
final products = <Product>[
for (int i = 0; i < quotationList.length; i++)
Product(
i.toString(),
quotationList[i][0],
quotationList[i][1],
quotationList[i][2],
),
];
The loops inside lists and maps don't have {}, because there aren't multiline.
this is a full working code:
void main() {
List quotationList = List();
quotationList.add(["name1", 10.0, 100]);
quotationList.add(["name2", 10.0, 100]);
quotationList.add(["name3", 10.0, 100]);
quotationList.add(["name4", 10.0, 100]);
List products = quotationList
.asMap()
.map((index, quotation) => MapEntry(
index,
Product(
index,
quotation[0].toString(),
quotation[1],
quotation[2],
)))
.values
.toList();
for (Product p in products) print(p.name);
}
class Product {
final int index;
final String name;
final double price;
final int n;
Product(this.index, this.name, this.price, this.n);
}
Hope it helps!
The conversion from List to Map is needed (asMap) because you need an index as well. If you do not need an index you can use the map method directly on the list.
try this
final products = [
for(int i=0; i<quotationList.length; i++)
{
Product(i.toString(), quotationList[i][0], quotationList[i][1], quotationList[i][2]),
}
];
Related
I have a list (in flutter):
loadedSummaryList = [
'BILD',
'DRIT',
'VIMN',
'WELT',
'FLUTTER',
'ALL'
];
, and I want to sort this list like:
['WELT', 'BILD', 'VIMN', 'DRIT', 'ALL', 'FLUTTER']
in other words, I want to sort the first four elements of the list always like 'WELT', 'BILD', 'VIMN', 'DRIT', and then alphabetically.
I tried it like this:
List<String> sortList = ['WELT', 'BILD', 'VIMN', 'DRIT'];
loadedSummaryList.sort(
(a, b) {
int aIntex = sortList.indexOf(a.name);
int bIntex = sortList.indexOf(b.name);
return aIntex.compareTo(bIntex);
},
);
which returns
['ALL', 'FLUTTER', 'WELT', 'BILD', 'VIMN', 'DRIT'];
but actually, I want to have it like:
['WELT', 'BILD', 'VIMN', 'DRIT', 'ALL', 'FLUTTER']
could someone help me, please?
thanks in advance
Just sort them and merge them into one.
void main() {
var all = <String>['BILD', 'DRIT', 'VIMN', 'WELT', 'FLUTTER', 'ALL'];
var sort = <String>['WELT', 'BILD', 'VIMN', 'DRIT'];
// It depends on how you want list sorting in the end result.
// You can sort both lists if you want.
all.sort();
//sort.sort();
var result = sort.followedBy(all).toSet().toList();
print(result); // [WELT, BILD, VIMN, DRIT, ALL, FLUTTER]
}
First thing, indexOf returns -1 when the element is not in the list, therefore it will put those in front. A solution for that is to change it to a higher number in that case.
Secondly, you also need to sort them alphabetically, which you don't do now. You can do that by doing a compareTo on the strings themselves in the case that the first compareTo returns 0.
final result:
loadedSummaryList.sort(
(a, b) {
int aIntex = sortList.indexOf(a);
int bIntex = sortList.indexOf(b);
if (aIntex == -1) aIntex = sortList.length;
if (bIntex == -1) bIntex = sortList.length;
var result = aIntex.compareTo(bIntex);
if (result != 0) {
return result;
} else {
return a.compareTo(b);
}
},
);
Here is my Dart code
var mp = new Map();
mp[[1,2]] = "Hi";
mp[[3,5]] = "sir";
mp.remove([3,5]);
print(mp);
Output here is null
How can i access value at mp[[3,5]]?
Two list instances containing the same elements is not equal to each other in Dart. This is the reason your example does not work.
If you want to create a Map which works like your example, you can use LinkedHashMap from dart:collection (basically the same when you are using Map()) to create an instance with its own definition of what it means for keys to be equal and how hashCode is calculated for a key.
So something like this if you want to have keys to be equal if the list contains the same elements in the same order. It should be noted it does not support nested lists:
import 'dart:collection';
void main() {
final mp = LinkedHashMap<List<int>, String>(
equals: (list1, list2) {
if (list1.length != list2.length) {
return false;
}
for (var i = 0; i < list1.length; i++) {
if (list1[i] != list2[i]) {
return false;
}
}
return true;
},
hashCode: Object.hashAll,
);
mp[[1, 2]] = "Hi";
mp[[3, 5]] = "sir";
mp.remove([3, 5]);
print(mp); // {[1, 2]: Hi}
}
I should also add that this is really an inefficient way to do use maps and I am highly recommend to never use List as keys in maps.
You add a list instance as a key to the Map object. You need the corresponding list instance to delete it again.
There are two ways to access
First;
final mp = {};
mp[[1,2]] = "Hi";
mp[[3,5]] = "sir";
mp.removeWhere((key, value) {
if(key is List){
return key.first == 3 && key[1] == 5;
}
return false;
});
Second;
final mp = {};
final key = [3, 5];
mp[[1,2]] = "Hi";
mp[key] = "sir";
mp.remove(key);
Map countries = {
"01": "USA",
"02": "United Kingdom",
"03": "China",
"04": "India",
"05": "Brazil",
"06": "Nepal",
"07": "Russia"
};
//method 1:
var _key = countries.keys.firstWhere((k)
=> countries[k] == 'Russia', orElse: () => null);
print(key); //output: 07
In my app, at many places I have used Lists like this:-
List<int> nums = [];
// initializing list dynamically with some values.
nums.length = 12; // increasing length of list
// setting these values afterward using nums[i] at different places.
Now after migrating to null-safety obviously nums.length = 4 is giving me a runtime error, so I was wondering is there any method to set the length of the list with default values such that, after if the length of the list was smaller than before then with new length extra elements are added with some default value.
Note: Of course I know we can use for loop, but I was just wondering if there is any easier and cleaner method than that.
var num = List<int>.generate(4, (i) => i);
You can read this.
Another approach:
extension ExtendList<T> on List<T> {
void extend(int newLength, T defaultValue) {
assert(newLength >= 0);
final lengthDifference = newLength - this.length;
if (lengthDifference <= 0) {
return;
}
this.addAll(List.filled(lengthDifference, defaultValue));
}
}
void main() {
var list = <int>[];
list.extend(4, 0);
print(list); // [0, 0, 0, 0];
}
Or, if you must set .length instead of calling a separate method, you could combine it with a variation of julemand101's answer to fill with a specified default value instead of with null:
class ExtendableList<T> with ListMixin<T> {
ExtendableList(this.defaultValue);
final T defaultValue;
final List<T> _list = [];
#override
int get length => _list.length;
#override
T operator [](int index) => _list[index];
#override
void operator []=(int index, T value) {
if (index >= length) {
_list.extend(index + 1, defaultValue);
}
_list[index] = value;
}
#override
set length(int newLength) {
if (newLength > length) {
_list.extend(newLength, defaultValue);
} else {
_list.length = newLength;
}
}
}
(I also made its operator []= automatically grow the ExtendableList if the specified index is out-of-bounds, similar to JavaScript.)
Your problem is that the List in Dart does not have the concept of adding more space while you promise that you are not going to use this new capacity before it is set.
But you can easily make your own List implementation which does this:
import 'dart:collection';
void main() {
List<int> nums = ExtendableList();
nums.length = 3;
nums[2] = 1;
nums[0] = 1;
nums[1] = 1;
print(nums); // [1, 1, 1]
nums.add(2);
print(nums); // [1, 1, 1, 2]
print(nums.runtimeType); // ExtendableList<int>
}
class ExtendableList<T> with ListMixin<T> {
final List<T?> _list = [];
#override
int get length => _list.length;
#override
T operator [](int index) => _list[index] as T;
#override
void operator []=(int index, T value) => _list[index] = value;
#override
set length(int newLength) => _list.length = newLength;
}
As you can see we are using a null type behind the scene but from the outside it will work like the list contains non-nullable. This only works because we assume the [] operator will not be called while a null value are in the list (which happens if we extend the list and does not set the value).
I should add that using such a List implementation does comes with great risk since you don't get any warning/error from the analyzer if you are using it wrongly.
You have to use a list of nullable element to make it longer.
List<int?> nums = [];
nums.length = 4; // OK
print(nums); // [null, null, null, null]
You can also use filled method. Here growable is false by default.
void main() {
var a = List<int>.filled(3, 0, growable: true);
print(a);
// [0, 0, 0]
}
Refer: https://api.flutter.dev/flutter/dart-core/List/List.filled.html
I have a list of objects of the same class.
This class contains an attribute I want to use.
I would like to get a list of all these attributes in one line. Is this possible?
Here is a small example: I just want a list of all the colors.
It is important that I return directly a list of these attributes, without the normal forEach statement.
void main() {
List<Car> listOfCars = [
Car('blue'),
Car('green'),
Car('yellow'),
];
}
//List<String> listOfColors = listOfCars[all].color;
class Car{
String color;
Car(this.color);
}
You can use the map function to achieve this
List<String> listOfColors = listOfCars.map((car) => car.color).toList();
print(listOfColors);
Just check out this code below:
void main() {
List<Car> listOfCars = [
Car('blue'),
Car('green'),
Car('yellow'),
];
List<String> stringList = List();
// This is where you get the single car object and then you add it the list of string
for (int i = 0; i < listOfCars.length; i++) {
stringList.add(listOfCars[i].color);
}
// this is the desired out put i have just printed your list :
print('This is the string length : ' + stringList.length.toString());
for (int i = 0; i < stringList.length; i++) {
print('This is the string list :' + stringList[i]);
}
}
class Car {
final String color;
Car(this.color);
}
Blow is the output :
This is the string length : 3
This is the string list :blue
This is the string list :green
This is the string list :yellow
I have a list of strings which I send to a queue. I need to split up the list so that I end up with a list of lists where each list contains a maximum (user defined) number of strings. So for example, if I have a list with the following A,B,C,D,E,F,G,H,I and the max size of a list is 4, I want to end up with a list of lists where the first list item contains: A,B,C,D, the second list has: E,F,G,H and the last list item just contains: I. I have looked at the “TakeWhile” function but am not sure if this is the best approach. Any solution for this?
You can set up a List<IEnumerable<string>> and then use Skip and Take to split the list:
IEnumerable<string> allStrings = new[] { "A", "B", "C", "D", "E", "F", "G", "H", "I" };
List<IEnumerable<string>> listOfLists = new List<IEnumerable<string>>();
for (int i = 0; i < allStrings.Count(); i += 4)
{
listOfLists.Add(allStrings.Skip(i).Take(4));
}
Now listOfLists will contain, well, a list of lists.
/// <summary>
/// Splits a <see cref="List{T}"/> into multiple chunks.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list">The list to be chunked.</param>
/// <param name="chunkSize">The size of each chunk.</param>
/// <returns>A list of chunks.</returns>
public static List<List<T>> SplitIntoChunks<T>(List<T> list, int chunkSize)
{
if (chunkSize <= 0)
{
throw new ArgumentException("chunkSize must be greater than 0.");
}
List<List<T>> retVal = new List<List<T>>();
int index = 0;
while (index < list.Count)
{
int count = list.Count - index > chunkSize ? chunkSize : list.Count - index;
retVal.Add(list.GetRange(index, count));
index += chunkSize;
}
return retVal;
}
Reference: http://www.chinhdo.com/20080515/chunking/
Some related reading:
Split a collection into `n` parts with LINQ?
Split List into Sublists with LINQ
LINQ Partition List into Lists of 8 members
Otherwise, minor variation on accepted answer to work with enumerables (for lazy-loading and processing, in case the list is big/expensive). I would note that materializing each chunk/segment (e.g. via .ToList or .ToArray, or simply enumerating each chunk) could have sideeffects -- see tests.
Methods
// so you're not repeatedly counting an enumerable
IEnumerable<IEnumerable<T>> Chunk<T>(IEnumerable<T> list, int totalSize, int chunkSize) {
int i = 0;
while(i < totalSize) {
yield return list.Skip(i).Take(chunkSize);
i += chunkSize;
}
}
// convenience for "countable" lists
IEnumerable<IEnumerable<T>> Chunk<T>(ICollection<T> list, int chunkSize) {
return Chunk(list, list.Count, chunkSize);
}
IEnumerable<IEnumerable<T>> Chunk<T>(IEnumerable<T> list, int chunkSize) {
return Chunk(list, list.Count(), chunkSize);
}
Test (Linqpad)
(note: I had to include the Assert methods for linqpad)
void Main()
{
var length = 10;
var size = 4;
test(10, 4);
test(10, 6);
test(10, 2);
test(10, 1);
var sideeffects = Enumerable.Range(1, 10).Select(i => {
string.Format("Side effect on {0}", i).Dump();
return i;
});
"--------------".Dump("Before Chunking");
var result = Chunk(sideeffects, 4);
"--------------".Dump("After Chunking");
result.Dump("SideEffects");
var list = new List<int>();
foreach(var segment in result) {
list.AddRange(segment);
}
list.Dump("After crawling");
var segment3 = result.Last().ToList();
segment3.Dump("Last Segment");
}
// test
void test(int length, int size) {
var list = Enumerable.Range(1, length);
var c1 = Chunk(list, size);
c1.Dump(string.Format("Results for [{0} into {1}]", length, size));
Assert.AreEqual( (int) Math.Ceiling( (double)length / (double)size), c1.Count(), "Unexpected number of chunks");
Assert.IsTrue(c1.All(c => c.Count() <= size), "Unexpected size of chunks");
}