I can successfully parse a comma-delimited list with dart-petitparser, but the same code fails when confronted with a space-delimited list:
class MyDefinition extends GrammarDefinition {
#override
Parser start() => throw UnsupportedError('Not yet.');
Parser commas() =>
ref0(number).separatedBy(char(','), includeSeparators: false);
Parser spaces() =>
ref0(number).separatedBy(char(' '), includeSeparators: false);
Parser<int> number() => digit().plus().flatten().trim().map(int.parse);
}
test('commas', () {
var defn = MyDefinition();
var parser = defn.build(start: defn.commas);
expect(parser.parse("7,4,9,5").value, [7, 4, 9, 5]); // PASS
});
test('spaces', () {
var defn = MyDefinition();
var parser = defn.build(start: defn.spaces);
expect(parser.parse("7 4 9 5").value, [7, 4, 9, 5]); // FAIL
});
It fails with the following:
Expected: [7, 4, 9, 5]
Actual: [7]
Which: at location [1] is [7] which shorter than expected
What am I doing wrong? I've dug through a bunch of the example grammars, and didn't find a whitespace-delimited list anywhere.
The .trim() parser in your number parser is consuming whitespaces before and after the number. This prevents the space-delimited list parser from finding a separating whitespace.
I suggest to rewrite as:
Parser spaces() =>
ref0(number).separatedBy(char(' ').plus(), includeSeparators: false);
// add this ^^^^^^^
Parser<int> number() =>
digit().plus().flatten().map(int.parse);
// remove trim, here ^
Related
I want To build a Program in which i want Multiple inputs in integers and Reverse it .. how Can I Do that in Dart?
I tried of strings But Don't Know About Integers
You can do something like this:
import 'dart:io';
void main() {
print('Input integers (q to stop):');
final integers = <int>[];
while (true) {
// Reads input from the user.
final input = stdin.readLineSync()!;
// Check to see if the user is done inputting numbers.
if (input == 'q') {
break;
}
// Try to convert the String to an int. If input isn't a
// valid integer, int.tryParse(input) == null.
final integer = int.tryParse(input);
if (integer != null) {
integers.add(integer);
}
}
print('Original order: $integers');
// Reversing a List in Dart is simple: just call integers.reverse
// to get an Iterable with the elements of integers in reversed order.
// Calling integers.reverse.toList() will convert the Iterable to a List
// so it's possible to print the entire list at once.
print('Reversed order: ${integers.reversed.toList()}');
}
Example:
Input integers (q to stop):
1
2
3
r
4
5
q
Original order: [1, 2, 3, 4, 5]
Reversed order: [5, 4, 3, 2, 1]
I'm having issues attempting to remove duplicate lists within a list. For example, using the list below, I need to remove one of the [2, 9] elements from the list.
List listOfLists = [[1, 5], [2, 9], [10, 12], [-1, 4], [2, 9]];
I have tried using toSet, but it only seems to work with a list of int or strings:
List uniqueLists = listOfLists.toSet().toList();
I have been stuck on this all morning, I'm sure its something simple, but the solution isn't coming to me. Any help would be appreciated.
The issue is that == for lists is reference equality, not based on the value of the lists.
for example if you run this program:
void main() {
print([2, 9] == [2, 9]);
}
it will print false.
You can create a HashSet (or LinkedHashSet if you want to preserve the order) with custom equals and hashcode functions.
import 'dart:collection';
import 'package:collection/collection.dart';
void main() {
List<List<int>> listOfLists = [
[1, 5],
[2, 9],
[10, 12],
[-1, 4],
[2, 9],
];
Set<List<int>> uniqueLists = HashSet<List<int>>(
equals: const ListEquality().equals,
hashCode: const ListEquality().hash,
)..addAll(listOfLists);
print(uniqueLists);
}
This solution uses the collection package for the ListEquality class.
This solution traverses the list backwards, and removes the last item when a duplicate is found. To compare lists, _listsAreEqual is used which is taken from this answer.
Less elegant compared to other solutions, but it does not require any additional packages.
bool _listsAreEqual(list1, list2) {
var i=-1;
return list1.every((val) {
i++;
if (val is List && list2[i] is List) {
return _listsAreEqual(val,list2[i]);
} else {
return list2[i] == val;
}
});
}
List _removeDuplicates(list) {
for (var i=list.length-1; i>0; i--) {
for (var j=i-1; j>=0; j--) {
if (_listsAreEqual(list[i], list[j])) {
list.removeAt(i);
break;
}
}
}
return list;
}
void main(){
List listOfLists = [[1, 5], [2, 9], [10, 12], [-1, 4], [2, 9]];
List uniqueLists = _removeDuplicates(listOfLists);
//List uniqueLists = _removeDuplicates(List.from(listOfLists)); // leave original list unmodified
print(uniqueLists);
}
If you do not want the original list to be modified, use the commented statement instead to create a copy of the original list.
Thank you for your help. Not sure why I didn't find this previously, but this does the trick perfectly.
List uniqueList = listOfLists.map((f) => f.toString()).toSet().toList().map((f) => json.decode(f) as List<dynamic>).toList();
I am trying to understand the const keyword I found an article on GeeksforGeeks of const but I didn't understand it if we make the [1,2] constant then geek1 == geek2 will print true otherwise false how?
// Declaring a function
gfg() =>[1, 2]; // if we write here gfg() => const [1, 2]; then geek1 == geek2 will print true
// Main function
void main() {
// Assiging value
// through function
var geek1 = gfg();
var geek2 = gfg();
// Printing result
// true
print(geek1 == geek2);
print(geek1);
print(geek2);
}
== for arrays in dart compares references. Meaning that two arrays, although with identical contents can return false on comparison with ==.
const defines a compile-time constant, but it would also work with a class attribute. It's just important, that instead of creating a new array, the function returns the same reference twice.
The difference between the two functions is essentially, that in the first one, you define a new array with each call of the function (different reference each time), while in the second one you define a compile-time constant, that is returned on each call of the function (same reference each time).
So let's see some examples:
class Factory {
List<int> arr = [1, 2];
final finalArr = [1, 2];
static const constArr = [1, 2];
getValue() => [1, 2];
getInlineConst() => const [1, 2];
getRef() => arr;
getFinalRef() => finalArr;
getConstRef() => constArr;
}
void main() {
final f = new Factory();
print("values: ${f.getValue() == f.getValue()}");
print("const inline: ${f.getInlineConst() == f.getInlineConst()}");
print("reference: ${f.getRef() == f.getRef()}");
print("final reference: ${f.getFinalRef() == f.getFinalRef()}");
print("const reference: ${f.getConstRef() == f.getConstRef()}");
final refBefore = f.getRef();
f.arr = [1, 2];
final refAfter = f.getRef();
print("reference (with change inbetween): ${refBefore == refAfter}");
}
Output is:
values: false
const inline: true
reference: true
final reference: true
const reference: true
reference (with change inbetween): false
Dart canonicalizes constants. That means that const Foo(1) in one part of the program evaluates to the same object as const Foo(1) in another part of the program. There is only one object. That extends to constant lists too: const [1, 2, 3] will evaluate to the same constant list everywhere it occurs in the program.
Non-constant object creation creates a new object each time its evaluated: Foo(1) or new Foo(1) will create a new object each time. Same for list iterals.
So, identical(const [1, 2, 3], const [1, 2, 3]) is true, but identical([1, 2, 3], [1, 2, 3]) is false.
The == of Dart's built-in lists does not compare the contents of the list. It's inherited from Object and only checks whether it's the same object (basically using bool operator==(Object other) => identical(this, other);).
I want to have a map with duplicate keys. Is there such a map in Dart or a utility library that has this functionality?
I'm using the following get a count of items:
myList.forEach(
(element) {
if (!myMap.containsKey(element)) {
myMap[element] = 1;
} else {
myMap[element] += 1;
}
},
);
then convert keys/values to lists: Need to switch key/values...
final keys = myMap.keys.toList();
final itemSpit = keys.map((e) => e.toString().split('§º')).toList();
final values = myMap.values.toList();
put it in a map
final map = Map();
for (var i = 0; i < values.length; i++) {
map[values[i]] = itemSpit[i];
}
Obviously the keys are overridden in the for loop.
then
iterate over map (Put keys/values in flutter widgets)
final cells = map.entries
.map((e) => ........
THe first method increases the value count if there's a duplicate value. So I have this. ... {breadwhitelarge: 3, cornyellowsmall:5 ..etc..}
I then have to split the strings and have output like this
5 bread white large
3 corn yellow small
Instead of defining a map which allows duplicated keys you can instead create a Map<K,List<V>> like this example:
void main() {
final map = <String, List<int>>{};
addValueToMap(map, 'Test 1', 1);
addValueToMap(map, 'Test 1', 2);
addValueToMap(map, 'Test 2', 3);
addValueToMap(map, 'Test 1', 4);
addValueToMap(map, 'Test 2', 5);
addValueToMap(map, 'Test 3', 6);
print(map); // {Test 1: [1, 2, 4], Test 2: [3, 5], Test 3: [6]}
}
void addValueToMap<K, V>(Map<K, List<V>> map, K key, V value) =>
map.update(key, (list) => list..add(value), ifAbsent: () => [value]);
You can then ask for a given key and get a list of all values connected to this key.
package:quiver provides a MultiMap class with List-based and Set-based implementations.
Could you just create the Flutter widgets directly from the first map?
var widgets = [for (var e in myMap.entries) MyWidget(
count: e.value,
strings: [... e.key.split("§º")])];
Building the intermediate map seems to be what is causing the trouble.
this is an example map has duplicate keys
withDuplicateKey() {
List<dynamic> demoList = [
{1},
{2},
{3},
{1}
];
var toRemove = {};
demoList.forEach((e) {
toRemove.putIfAbsent(e, () => e);
});
print(toRemove.keys.toList());
}
output is ( printed list of key )
[{1}, {2}, {3}, {1}]
This question already has answers here:
Creating function with variable number of arguments or parameters in Dart
(6 answers)
Closed 5 years ago.
Is there a way in Dart to pack/unpack arguments in a function (like Python for example) ?
For packing example, being able to declare a function like this :
packArguments(*listOfArguments, **mapOfArguments) {
listOfArguments.forEach((arg) => print(arg));
mapOfArguments.forEach((key, val) => print("$key => $val"));
}
And then doing this :
packArguments("I", "Put", "whatever", "I", "want, arg1: "A", arg2: 1);
Would display :
I
Put
whatever
I
want
arg1 => A
arg2 => 1
As for unpacking, being able to do something like that :
functionWithLotOfArgument(a, b, c, d, e, {aa, bb = null, cc = null}) {
// do stuff
}
var argList = [1, 2, 3, 4, 5];
var argMap = {"aa": "haha", bb: "baby"};
functionWithLotOfArgument(*argList, **argMap);
Related issue https://github.com/dart-lang/sdk/issues/29087
This is not currently supported, but you can very easily pack yourself, by passing a list & map:
void packArguments(List listOfArguments, Map mapOfArguments) {
listOfArguments.forEach((arg) => print(arg));
mapOfArguments.forEach((key, val) => print("$key => $val"));
}
void main() {
packArguments(['a', 3], {'arg1': 'a', 'arg2': 5});
}
https://dartpad.dartlang.org/98ed3a3b07a2cca049cde69ca50ca269