We have two lists
List<String> list1 = ['foo', 'bar', 'blah', 'bee', 'fog'];
List<String> list2 = ['bee', 'bar'];
and we'd like to remove from the first the items in the second.
We can iterate, removing those in the second one by one
for (var v in list2) {
list1.removeWhere((item) => item == v);
}
but that's silly. It'll take time proportional to the product of the length of the two lists.
We can convert to sets and use Dart's Set.difference(), then return a list.
n = (n.toSet().difference(m.toSet())).toList();
but we lose the order of the items in list1.
What's a good way for determining stable list set-difference in Dart?
A solution would be to convert list2 into a Set to make it more efficient to ask if an element from list1 is part of list2. We can then use removeWhere to remove elements from list1:
void main() {
List<String> list1 = ['foo', 'bar', 'blah', 'bee', 'fog'];
List<String> list2 = ['bee', 'bar'];
list1.removeWhere(list2.toSet().contains);
print(list1); // [foo, blah, fog]
}
Related
I have a list of elements and I need to get a list containing the first element followed by every nth element afterwards. For example: given n = 3 and the list [banana, cherry, apple, pear, kiwi], I need to get the list [banana, pear]. I need this regardless of specific content, since the list depends on user input.
How do I do this using Dart?
You may access list in dart by providing an index like for example:
List<String> fruits = ["banana","cherry","apple","pear","kiwi"];
print(fruits[0]); // Will print to the console "banana";
On your case, you are trying to access index 0 and index 3 which is "banana" and "pear".
You may create a function that accepts an index like:
String getFruit(int index, List<String> fruits) => fruits[index];
print(getFruit[0]); // Will print "banana";
or if you need to actually get the specific ranges you may use:
List<String> fruits =["banana","cherry","apple","pear","kiwi"].getRange(0,4);
// Will give you "banana","cherry","apple","pear
You may check : https://api.dart.dev/be/180791/dart-core/List-class.html for more information.
Edited answer based off the comment:
List<String> getElements(List userInput, nIndex){
List elements = [];
for(int x = 0; x<userInput.length;x++){
if(x % nIndex == 0){
elements.add(userInput[x]);
}
}
return elements;
}
List fruits = ["banana","cherry","apple","pear","kiwi"];
print(getElements(fruits,2));
or you may try to look and use List.retainWhere() depending on your use case.
Dart has a great set of collection operators that make this type of problem pretty straightforward to solve. For example, we could do something like:
extension X<T> on List<T> {
List<T> everyNth(int n) => [for (var i = 0; i < this.length; i += n) this[i]];
}
main() {
final fruit = ["banana", "cherry", "apple", "pear", "kiwi"];
print(fruit.everyNth(3));
}
Output:
[banana, pear]
You can use this extension method, which will work on lists of any type:
extension GetEveryN<T> on List<T> {
List<T> elementsEveryN(int n) {
List<T> result = [];
for(int index = 0; index < length; index +=1) {
if(index % n == 0) {
result.add(this[index]);
}
}
return result;
}
}
Trying it in an example:
List<String> list = ["banana", "cherry","apple", "pear","kiwi"];
print(list.elementsEveryN(2)); // [banana, pear]
I want to know how this work it should remove the item in list number 3 which is 'four' and print 'one','two','Three' why it is print three, four
here is the code:
final numbers = <String>['one', 'two', 'three', 'four'];
numbers.removeWhere((item) => item.length == 3);
print(numbers); // [three, four]`
removeWhere :Removes all objects from this list that satisfy test.
An object o satisfies test if test(o) is true.
removeWhere will go through the list and find the matched item, means where we do our logic and return true.
You can see item.length==3 is true for 'one' and 'two' because its string length is 3, that's why these elements are removed. You can find more on List
You can expand the method like
numbers.removeWhere((item) {
bool isItemContains3Char = item.length == 3;
print("${isItemContains3Char} : $item length : ${item.length}");
return isItemContains3Char;
});
All you need to return true based on your logic from removeWhere to remove elements.
final numbers = <String>['one', 'two', 'three', 'four'];
numbers.removeAt(2);
print(numbers);
output
[one, two, four]
I'm trying to fetch the randomly specific number of items from one list and add them to the other list but without duplication.
For example: pick three random items from the list randomly and put them into another list. This is what I have achieved so far but this could pick the duplicate item again.
List itemList = ['NAME1', 'NAME2', 'NAME3', 'NAME4', 'NAME3', 'NAME5', 'NAME2'];
List randomItems = [];
for(var i=0; i<=2; i++){ // run the loop for three times
int randomNumber = Random().nextInt(itemList.length); //generate random number within itemList range
randomItems.add(itemList[randomNumber]); // duplication occur, for example: NAME2 could be added two times
}
There are several steps we can do to solve this problem. First, we want to get rid of the duplicate elements in the list. We can here do that by converting the list to a Set:
List<String> itemList = [
'NAME1',
'NAME2',
'NAME3',
'NAME4',
'NAME3',
'NAME5',
'NAME2'
];
Set<String> itemSet = itemList.toSet();
print(itemSet); // {NAME1, NAME2, NAME3, NAME4, NAME5}
Then, we want to extract 3 random elements from this new Set in such a way that we can't select the same element twice. The easiest way to solve this is by shuffle the elements randomly and then take elements from our collection. But Set does not have the concept of any specific "order" and we can't therefore shuffle our Set.
So let's convert our Set back to a List:
Set<String> itemSet = itemList.toSet();
List<String> itemListFromSet = itemSet.toList();
print(itemListFromSet); // [NAME1, NAME2, NAME3, NAME4, NAME5]
We can then shuffle this new list:
itemListFromSet.shuffle();
print(itemListFromSet); // [NAME3, NAME2, NAME4, NAME5, NAME1]
If we then want 3 random selected elements, we can just take 3 elements from this randomly ordered list. So e.g. (take returns an iterable which we then makes a new list of):
List<String> randomItems = itemListFromSet.take(3).toList();
A complete solution would look like:
void main() {
List<String> itemList = [
'NAME1',
'NAME2',
'NAME3',
'NAME4',
'NAME3',
'NAME5',
'NAME2'
];
Set<String> itemSet = itemList.toSet();
List<String> itemListFromSet = itemSet.toList();
itemListFromSet.shuffle();
List<String> randomItems = itemListFromSet.take(3).toList();
print(randomItems); // [NAME5, NAME2, NAME4]
}
Which can be reduced down to:
void main() {
List<String> itemList = [
'NAME1',
'NAME2',
'NAME3',
'NAME4',
'NAME3',
'NAME5',
'NAME2'
];
List<String> randomItems =
(itemList.toSet().toList()..shuffle()).take(3).toList();
print(randomItems); // [NAME3, NAME4, NAME2]
}
I have a list1: var list1 = ["a:1", "b:2", "c:3"];
how can I create list2 based on list1 like this: ["a", "b", "c"]
I thought I would have to use split and forEach but I don't know how to combine it
Maybe this works for you, if and only if you always have the same String length
List<String> list1 = ["a:1", "b:2", "c:3"];
List<String> list2 = list1.map((f) => f.substring(0,1)).toList();
Or if you wanted to have ":" as the basis regardless of the String length for each element then you can try the code below
List<String> list1 = ["a:1", "b:2", "c:3"];
List<String> list2 = list1.map((f) => f.split(":")[0]).toList();
Iterate through all items of the list with forEach.
With every item (which is a string), split it using ':' as separator (or, if its always just one character, simply get the first charaxter of the item.
Add the first element of the result of split (or aimply first charaxter of item) to list2.
var list1 = ["a:1", "b:2", "c:3"];
List list2;
list1.asMap().forEach((key, value) {
list2.add(value.replaceAll(':${key + 1}', ''));
});
Here is my code
I have two lists that are the same length:
List<List<String>> list1 = [["John","Omar","Jane"],["Rick","Hulie","Frank"],["Pri","Mary","Tim"]]
List<int> list2 = [1,5,9]
I want to add insert the numbers from list2 to the start of the lists in list1 like this..
list3 to look like
[["1","John","Omar","Jane"],["5", "Rick","Hulie","Frank"],["9","Pri","Mary","Tim"]]
You can loop through the list and insert each of the numbers at index 0.
List<List<String>> list1 = [["John","Omar","Jane"],["Rick","Hulie","Frank"], ["Pri","Mary","Tim"]];
List<int> list2 = [1,5,9];
for (int i = 0;i < list1.length;i++) {
list1[i].insert(0,list2[i].toString());
}
// if you want a more dart like the solution then use this.
list1.asMap().forEach((index,value) => value.insert(0,list2[index].toString()));