Filtering arrays in Dart - dart

Can anyone guide me and tell me where I am making mistake in the code.
I want to filter all the food which have Pizzatype veggie.
I am getting an empty array in the output.

where iterates one pizza at a time. Something like this might work.
final findVeggiePizza = pizzaList.where((pizza) => pizza.type == PizzaType.veggie).toList();

Probably as so
enum PizzaType {
veggie,
meatLover
}
class PizzaWithToppings {
String typeDes;
int price;
List list;
PizzaType type;
PizzaWithToppings(this.typeDes, this.price, this.list, this.type);
bool filter(PizzaType type) {
return this.type == type;
}
}
void main() {
final pizzaWithToppings =
PizzaWithToppings('Mushroom Pizza', 12, [1, 2, 3], PizzaType.veggie);
final pizzaWithToppings2 =
PizzaWithToppings('Chiken Pizza', 20, [1, 2, 3], PizzaType.meatLover);
final pizzaWithToppings3 =
PizzaWithToppings('Veggie Pizza', 15, [1, 2, 3], PizzaType.veggie);
final pizzaList = [pizzaWithToppings, pizzaWithToppings2,pizzaWithToppings3];
final findVeggiePizza = pizzaList.where((pizza) => pizza.filter(PizzaType.veggie)).toList();
print (findVeggiePizza);
}
Is that so?

Related

Use reduce method in dart to group consecutive elements in the list like in Javascript

I have following codes in javascript
var ArrayLogs = [1, 3, 5, 4, 9, 11, 0, -4, -10];
var newLogArrays = [];
ArrayLogs.reduce(function(result, value, index, array) {
if (index % 2 === 0){
newLogArrays.push(array.slice(index, index + 2));
}
return newLogArrays;
}, []);
Above method outputs:
[[1,3],[5,4],[9,11],[0,-4],[-10]]
I am looking equivalent code in Dart, I know there is reduce method in dart as well, but I am not sure how to use to get similar result as javascript.
Any help will be highly appreciated.
Thanks
If you just want to do it using Dart only, you can do something like the following:
void main() {
final arrayLogs = [1, 3, 5, 4, 9, 11, 0, -4, -10];
final result = arrayLogs.fold<List<List<int>>>([], (list, element) {
if (list.isEmpty || list.last.length > 1) {
return list..add([element]);
} else {
return list..last.add(element);
}
});
print(result);
// [[1, 3], [5, 4], [9, 11], [0, -4], [-10]]
}
I am sure there are some packages which can do this more automatically or cleaner.

How can i find sum of three element in a given away

Is there a method we use to reach the desired number in an array given in dart language.. I can do this for binary ones, but I can't do it for a code that finds the sum of 3 or more elements
For example
Input: candidates = [10,1,2,7,6,1,5], target = 8
Output:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]
this is the my code i have done until now
void main() {
var candidates = [10, 1, 2, 7, 6, 1, 5], target = 8;
var answer = [];
for (int i = 0; i < candidates.length; i++) {
for (int j = 0; j < candidates.length; j++) {
if (candidates[i] + candidates[j] == target && i != j && i < j) {
answer.add([candidates[i], candidates[j]]);
}
}
}
}
I am sure this can be done more efficient but since the solution is for some Leetcode assignment, I don't really want to spend too much time on optimizations.
I have tried added some comments in the code which explains my way of doing it:
void main() {
getSumLists([10, 1, 2, 7, 6, 1, 5], 8).forEach(print);
// [5, 1, 2]
// [1, 6, 1]
// [1, 7]
// [6, 2]
getSumLists([2, 5, 2, 1, 2], 5).forEach(print);
// [2, 1, 2]
// [5]
}
Iterable<List<int>> getSumLists(
List<int> candidates,
int target, {
List<int>? tempAnswer,
int sum = 0,
}) sync* {
// We cannot use default value in parameter since that makes list const
final tempAnswerNullChecked = tempAnswer ?? [];
if (sum == target) {
// We got a result we can return.
// OPTIMIZATION: If you know the returned list from each found result is not
// being used between found results, you can remove the `.toList()` part.
yield tempAnswerNullChecked.toList();
} else if (sum > target) {
// No need to search further in this branch since we are over the target
return;
}
// Make a copy so we don't destroy the input list but also so it works even
// if provided list as input is non-growing / non-modifiable
final newCandidates = candidates.toList();
while (newCandidates.isNotEmpty) {
// We take numbers from the end of the list since that is more efficient.
final number = newCandidates.removeLast();
// Recursive call where we return all results we are going to find given
// the new parameters
yield* getSumLists(
newCandidates,
target,
tempAnswer: tempAnswerNullChecked..add(number),
sum: sum + number,
);
// Instead of creating a new tempAnswerNullChecked, we just reuse it and
// make sure we remove any value we are temporary adding
tempAnswerNullChecked.removeLast();
// Ensure we don't get duplicate combinations. So if we have checked the
// number `1` we remove all `1` so we don't try the second `1`.
newCandidates.removeWhere((element) => element == number);
}
}

Removing duplicates from list of lists

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();

How can I filter a map / access the entries

The Map interface doesn't seem to provide access to the entries as an iterable, nor does it expose a where method to filter entries. Am I missing something? Is there a simple workaround?
e.g.
Map map;
final filteredMap = map.where((k, v) => k.startsWith("foo"));
Update: with control flow collection statements you can also do this:
final filteredMap = {
for (final key in map.keys)
if (!key.startsWith('foo')) key: map[key]
};
Original answer: Dart 2.0.0 added removeWhere which can be used to filter Map entities. Given your example, you could apply this as:
Map map;
final filteredMap = Map.from(map)..removeWhere((k, v) => !k.startsWith("foo"));
It's not the where method you asked for, but filtering Map entities is certainly doable this way.
Since Dart 2.0 Maps have an entries getter that returns an Iterable<MapEntry<K, V>> so you can do:
MapEntry theOne = map.entries.firstWhere((entry) {
return entry.key.startsWith('foo');
}, orElse: () => MapEntry(null, null));
You can use
library x;
void main(List<String> args) {
Map map = {'key1': 'aölsjfd', 'key2': 'oiweuwrow', 'key11': 'oipoip', 'key13': 'werwr'};
final filteredMap = new Map.fromIterable(
map.keys.where((k) => k.startsWith('key1')), key: (k) => k, value: (k) => map[k]);
filteredMap.forEach((k, v) => print('key: $k, value: $v'));
}
I use dartx and it's filter method
var myMap = {
"a": [1, 2, 3],
"b": [4, 5, 6],
"c": [7, 8, 9],
};
var result = myMap.filter((entry) => entry.key != "a");
You can just create an extension function and then use it anywhere in your code.
Put this in any file (I called mine MapUtils.dart)
extension MapUtils<K, V> on Map<K, V> {
Map<K, V> where(bool Function(K, V) condition) {
Map<K, V> result = {};
this.entries.forEach((element) {
if (condition(element.key, element.value)) {
result[element.key] = element.value;
}
});
return result;
}
}
and then use it like so:
Map<String, int> peopleHeight = {"Bob":170, "Alice":130};
Map<String, int> shortPeople = peopleHeight.where((name, height) => height < 140);

Dart List min/max value

How do you get the min and max values of a List in Dart.
[1, 2, 3, 4, 5].min //returns 1
[1, 2, 3, 4, 5].max //returns 5
I'm sure I could a) write a short function or b) copy then sort the list and select the last value,
but I'm looking to see if there is a more native solution if there is any.
Assuming the list is not empty you can use Iterable.reduce :
import 'dart:math';
main(){
print([1,2,8,6].reduce(max)); // 8
print([1,2,8,6].reduce(min)); // 1
}
If you don't want to import dart: math and still wants to use reduce:
main() {
List list = [2,8,1,6]; // List should not be empty.
print(list.reduce((curr, next) => curr > next? curr: next)); // 8 --> Max
print(list.reduce((curr, next) => curr < next? curr: next)); // 1 --> Min
}
You can now achieve this with an extension as of Dart 2.6:
import 'dart:math';
void main() {
[1, 2, 3, 4, 5].min; // returns 1
[1, 2, 3, 4, 5].max; // returns 5
}
extension FancyIterable on Iterable<int> {
int get max => reduce(math.max);
int get min => reduce(math.min);
}
An example to get Min/Max value using reduce based on condition for a list of Map objects
Map studentA = {
'Name': 'John',
'Marks': 85
};
Map studentB = {
'Name': 'Peter',
'Marks': 70
};
List<Map> students = [studentA, studentB];
// Get student having maximum mark from the list
Map studentWithMaxMarks = students.reduce((a, b) {
if (a["Marks"] > b["Marks"])
return a;
else
return b;
});
// Get student having minimum mark from the list (one liner)
Map studentWithMinMarks = students.reduce((a, b) => a["Marks"] < b["Marks"] ? a : b);
Another example to get Min/Max value using reduce based on condition for a list of class objects
class Student {
final String Name;
final int Marks;
Student(this.Name, this.Marks);
}
final studentA = Student('John', 85);
final studentB = Student('Peter', 70);
List<Student> students = [studentA, studentB];
// Get student having minimum marks from the list
Student studentWithMinMarks = students.reduce((a, b) => a.Marks < b.Marks ? a : b);
If your list is empty, reduce will throw an error.
You can use fold instead of reduce.
// nan compare to any number will return false
final initialValue = number.nan;
// max
values.fold(initialValue, (previousValue, element) => element.value > previousValue ? element.value : previousValue);
// min
values.fold(initialValue, (previousValue, element) => element.value < previousValue ? element.value : previousValue);
It can also use to calculate sum.
final initialValue = 0;
values.fold(initialValue, (previousValue, element) => element.value + previousValue);
Although fold is not cleaner than reduce for getting min/max, it is still a powerful method to do more flexible actions.
For empty lists: This will return 0 if list is empty, the max value otherwise.
List<int> x = [ ];
print(x.isEmpty ? 0 : x.reduce(max)); //prints 0
List<int> x = [1,32,5];
print(x.isEmpty ? 0 : x.reduce(max)); //prints 32
int minF() {
final mass = [1, 2, 0, 3, 5];
mass.sort();
return mass[0];
}
void main() {
firstNonConsecutive([1,2,3,4,6,7,8]);
}
int? firstNonConsecutive(List<int> arr) {
var max = arr.reduce((curr, next) => curr > next? curr: next);
print(max); // 8 --> Max
var min = arr.reduce((curr, next) => curr < next? curr: next);
print(min); // 1 --> Min
return null;
}
If you need a more sophisticated min/max, such as finding an object with a min/max of a field, or use of a comparison predicate, use minBy() and maxBy() from the collection package:
import 'package:collection/collection.dart';
class Person {
final String name;
final int age;
Person(this.name, this.age);
#override
String toString() => '$name (age $age)';
}
main() {
final alice = Person('Alice', 30);
final bob = Person('Bob', 40);
final chris = Person('Chris', 25);
final dan = Person('Dan', 35);
final people = [alice, bob, chris, dan];
print('Youngest is ${minBy(people, (e) => e.age)}');
print('Oldest is ${maxBy(people, (e) => e.age)}');
print('First alphabetically is ${minBy(people, (e) => e.name)}');
print('Last alphabetically is ${maxBy(people, (e) => e.name)}');
print('Largest name length times age is ${maxBy(people, (e) => e, compare: (a, b) => (a.name.length * a.age).compareTo(b.name.length * b.age))}');
}
Output:
Youngest is Chris (age 25)
Oldest is Bob (age 40)
First alphabetically is Alice (age 30)
Last alphabetically is Dan (age 35)
Largest name length times age is Alice (age 30)```

Resources