Convert string to list of ints - dart

I have a string like this "1, 2, 3, 4, 5, 10, 23, 54"
I can do this by first converting it to list of string
List<String> list = str.split(",");
Then I have to loop the list and cast it to int.
Is it possible to convert the above string to List<int> in one line?
Edit 1:
I tried
List<int> ints = "1,2,3".split(",").map((i) => int.parse(i));
But I got 'MappedListIterable<String, int>' is not a subtype of type 'List'
Edit 2:
I found the solution. But I am not very clear.
List<int> ints = "1,2,3".split(",").map((i) => int.parse(i)).toList();
This solves the problem.
But what is the difference between adding toList() and not adding toList() in dart? Can someone explain please?

When using the Map method, it actually returns a MappedIterable (in this case a MappedListIterable) (The documetation for this) instance instead of List, so you need to cast it into a list instance.
That's why adding toList() is working because it actually converts to MappedListIterable into a List.
List<int> ints = "1,2,3".split(",").map((i) => int.parse(i)).toList();

The map method returns an iterable, not a list. It is lazy, so if you follow map(...) with .first, it will only convert the first element.
If you add .toList(), the you eagerly extract all the values from the iterable and create a list containing those values. Since you were asking for a list, you need to do this (an iterable is not necessarily a list).
Another one-liner would be:
List<int> ints = [for (var n in string.split(",")) int.parse(n)];
Alternatively, you can piggy-back on JSON decoding and do:
import "dart:convert";
...
list<int> ints = jsonDecode("[$string]");

Related

Cannot add elements into list inside map body

When executing the following code , no items added to list named x , Any idea why ?
I know if i loop normally over it, it will work but i just wonder why it behaves like that
List<int> x = [];
List<int> y = [1,2,3,4];
y.map((item) => x.add(item +2));
The .map() method returns a lazily evaluated Iterable:
Returns a new lazy Iterable with elements that are created by calling toElement on each element of this Iterable in iteration order.
Since you don't consume the returned Iterable, it will not trigger the method provided to map() and nothing happens.
You can instead use the forEach() method which will run on each elements in your list immediately.

How can I grab the last N elements in a Map<int, dynamic>?

I currently have a Map<int, dynamic> where the key is an order of insertion.
For example
const Map<int, dynamic> log = {
1: {'startDate': 1111, 'endDate': 2222},
2: {'startDate': 123123, 'endDate': 1231233},
3: {'startDate': 555555, 'endDate': 5555556},
4: {'startDate': 888888},
};
Now how can I get the last X amount?
I was thinking of
final Iterable<int> numberOfLogs = log.keys;
final Iterable<int> reversedNumberOfLogs = numberOfLogs.toList().reversed;
final Iterable<int> recent2Logs = reversedNumberOfLogs.take(2);
And then I could loop through the recent2Logs and then access the log Map by the looped index?
Is there a better way to do this?
Note that Map's and Set's default implementations are a LinkedHashMap and LinkedHashSet respectively, which already preserve insertion order for you when iterating over them. Taking advantage of that, you could use a Set (or an explicit LinkedHashSet) instead and do:
log.toList().reversed.take(2)
directly. If you still need the integer keys (because you might want to be able to efficiently remove the nth entry) and need to continue using a Map/LinkedHashMap, then that'd be:
log.entries.toList().reversed.take(2)
I was able to do
final recent2Logs = log.key.toList().getRange(log.length - 2, log.length));

Dart: Sorting by length of a list in a list of lists

I want a function that takes a list of lists. It should sort this list of lists, regardless of its type, by the length of each list within it.
I thought I could achieve this by using the function below, but I am getting type errors. X is not a subtype of Y. From my understanding, using dynamic means it can take any type, so what am I doing wrong?
List<List<dynamic>> sortByLength(List<List<dynamic>> lss) {
final newLss = List.from(lss);
return newLss..sort((a, b) => a.length.compareTo(b.length));
}
Your problem is that you accidentally converted a List<List<dynamic>> to a List<dynamic> and then tried to return that as a List<List<dynamic>> without a cast.
final newLss = List.from(lss);
This makes two mistakes:
It uses List.from instead of List.of (or instead of lss.toList() or [...lss]).
It does not specify an explicit type for the List.
Combined, those mistakes give newLss a type of List<dynamic>. Attempting to return newLss then fails because converting List<dynamic> to List<T> requires using List.cast to change the element type.

Dart: how to apply function to each inner element of list of lists

Obviously playing with dart and still new to it and implementing tic tac toe. So I have a list of lists of winning positions and want to check if any of the lists is sublist of the inputed moves list. Sounds pretty easy right, so I apply for each element of inner list I wanna check my condition. What are the dart ways to achieve this. This isn't working because map expect function of type void and I return some calls to print for each element of every inner list obviously. Why it isn't showing me any mistake at all.
I tried with .forEach and .takeWhile examples but coudn't get it working.
List <List<int>> winMoves = new List.generate(8, (i) => new List(3));
winMoves[0]=[1,2,3];
winMoves[1]=[4,5,6];
winMoves[2]=[7,8,9];
winMoves[3]=[1,4,7];
winMoves[4]=[2,5,8];
winMoves[5]=[3,6,9];
winMoves[6]=[1,5,9];
winMoves[7]=[3,5,7];
winMoves.map((list) => (list.forEach((el) => print(el))));
import 'package:collection/collection.dart' show ListEquality;
...
const eq = const ListEquality<int>();
print(winMoves.indexWhere((list) => eq.equals(list, [1, 5, 9])));
Depending on what result you want you can also use where, firstWhere, any, ...
There are many ways to solve this problem, depending on what the exact desired result is.
You have a list of elements, and you want to check something about these elements (in this case the elements are lists too, but that's not important to begin with).
If you want to know whether any of the elements satisfies your check, you can use:
bool hasWin = winMoves.any((moves) => ...check...);
If you want to find an element which satisfies your check, you can use:
var win = winMoves.firstWhere((moves) => ...check..., orElse: null);
If you want to find all the winners:
var wins = winMoves.where((moves) => ...check...).toList(); // `where` is lazy.
How to write the check is a separate issue. In this case you seem to want, as Günther Zöchbauer has already written, something like
(moves) => moves.every(expectedMoves.contains)
Your example is not giving you any warnings or errors because it's correct, and it doesn't actually do anything. The map function is lazy, it creates an Iterable which won't do anything until you start iterating. If you call .toList() on it, it'll create a List<void>. Not very useful, but valid in Dart 2.
Also, your initial winMoves initialization is overly complex. You can just do:
List<List<int>> winMoves = []..length = 8; // for growable list, or
List<List<int>> winMoves = List(8); // for fixed-length list.
You actively fill the list with lists, then immediately overwrite those values with new lists in the following lines.

Ruby Calling Join on an Array versus String

I have a script that creates an array , then adds items to the array depending on certain circumstances. In most cases, the array will end up with several values inside of it. Occasionally, the array will only hold one value inside of it.
After preparing this array, I usually call .join(",") to create a comma-separated string of all the array values:
tags.join(",")
It works fine when the array has multiple values, but when it only has one value it throws an error:
NoMethodError: undefined method 'join' for "Whatever the array value": String
Any idea why this is? What is the easiest way to resolve this? Do I need to do an if statement to check if the variable is an array or string? Seems a bit silly...let me know if I am missing something here.
If obj is your object, you can write
[*obj].join
For example
arr = ["Fa", "bu", "lo", "us!"]
[*arr].join #=> "Fabulous!"
str = "Whoa!"
[*str].join #=> "Whoa!"
This works because
[*arr] #=> ["Fa", "bu", "lo", "us!"] == arr
[*str] #=> ["Whoa!"]
Similarly,
[*[1,2,3]].join #=> "123"
[*7].join #=> "7"
You can use join on an array as following way :
#array = ["this","is","join","method","example"]
#array.join(" ")
"this is join method example"
#array.join("_")
"this_is_join_method_example"
In the case of a single element (say, 'Hello'), you should be calling join on an array, not the string itself; for example, ['Hello'].join(",") rather than 'Hello'.join(","). Of course, if there's only one element join doesn't actually do anything, so you could just use a conditional if to skip it... but that's kinda ugly. Most of the time, I'd use the construction Array(tags).join(","). If passed a single string, that'll wrap it in an array; if passed an array, it's a noop, returning the array as-is.

Resources