I am trying to exclude elements from a list of strings that contain any element from a separate list of strings to produce a third list of remaining strings from the first list.
var original_list = ['cigar', 'rebut', 'focal', 'blush', 'naval', 'bench'];
var exclusion_list = ['e', 'f'];
var result_list = [];
I'm still getting familiar with Dart syntax. In Python, I would have done something similar to:
for item in original_list:
if not any(letter in original_list for letter in exclusion_list):
result_list.append(item)
I've been going round and round in dartpad trying to come up with an elegant solution but I keep coming back to some ugly nested for loops.
Any help would be appreciated!
CodePudding user response:
I've landed on this
var list1 = ['cigar', 'rebut', 'focal', 'blush', 'naval', 'bench'];
var list2 = ['e', 'f'];
var remaining = [];
int flag;
for(int i = 0;i < list1.length;i ) {
flag = 0;
for(int j = 0; j < list2.length;j ) {
if(list1[i].contains(list2[j])) {
flag = 1;
continue;
}
}
if(flag==0) {
remaining.add(list1[i]);
}
}
Not the most elegant but it will "filter" out the strings in list1 that contain the characters in list2.
CodePudding user response:
The brutes-force implementation would be:
List<String> source = ...;
List<String> disallowedSubstrings = ...;
// ...
var result = <String>[];
outer:
for (var value in source) {
for (var exception in disallowedSubstrings) {
if (value.contains(exception)) {
continue outer;
}
}
result.add(value);
}
That's basically what you have, but using a label to continue the outer loop, instead of a flag to avoid doing more work inside it.
The inner loop can be replaced using any
, becoming:
if (exception.any(value.contains)) {
continue outer;
}
result.add(value);
It uses the Iterable.any
method to check something for every element of disallowedSubstrings
, and a method tear-off to do pass in a function which effectively does (x) => value.contains(x)
.
But then we have an if
, and might as well write it to guard the rest of the loop body, instead of continuing:
if (!disallowedSubstrings.any(value.contains)) {
result.add(value);
}
That leaves us with a for
and an if
doing an add
, which we can turn into a list literal:
var result = [for (var value in source)
if (!disallowedSubstrings.any(value.contains)) value
];
That's much closer to the Python version.
Alternatively, if not using a list literal, it can also be written as:
var result = source.where((value) =>
!disallowedSubstrings.any(value.contains)
).toList();