Dart: split a list to two sublists based on condition - list

Have there any way to split a list in dart based on a condition like following:
[1, 2, 3, 4, 5, 6, 7, 8] (A sample list)
After splitting it based on i % 2 == 0 condition,
it would generate the following two lists:
1) [1, 3, 5, 7]
2) [2, 4, 6, 8]
I know I can simply write a loop to go through all the elements and check the condition to create the two sublists. But have there any shorter functional way in dart?
Thanks in advance!

If you want to do this a lot it could be a good idea to create an extension method in your project which does what you want. I have come up with the following design which should work in a generic and efficient way:
void main() {
final s_list = [1, 2, 3, 4, 5, 6, 7, 8];
final match = s_list.splitMatch((element) => element % 2 == 0);
print(match.matched); // [2, 4, 6, 8]
print(match.unmatched); // [1, 3, 5, 7]
}
extension SplitMatch<T> on List<T> {
ListMatch<T> splitMatch(bool Function(T element) matchFunction) {
final listMatch = ListMatch<T>();
for (final element in this) {
if (matchFunction(element)) {
listMatch.matched.add(element);
} else {
listMatch.unmatched.add(element);
}
}
return listMatch;
}
}
class ListMatch<T> {
List<T> matched = <T>[];
List<T> unmatched = <T>[];
}

A quick solution:
var s_list = [1, 2, 3, 4, 5, 6, 7, 8];
s_list.where( (el) => el % 2 == 0 ).toList();
s_list.where( (el) => el % 2 != 0 ).toList();

Related

Remove duplicates pairwise in kotlin

I have multiple lists of integers.
val firstList: ArrayList<Int> = arrayListOf(1, 1, 1, 2, 3, 4)
val secondList: ArrayList<Int> = arrayListOf(1, 4, 5, 6, 6, 6, 7, 8)
val thirdList: ArrayList<Int> = arrayListOf(1, 6, 9)
...
I need to remove duplicates only among the other lists, and not within a list itself.
The result should be:
[1,1,1,2,3,4,5,6,6,6,7,8,9]
What is the best approach to do so in Kotlin?
We can filter the additional lists with a .filter and .contains, then add the result to the firstList. Not sure if this is the most efficient way, but it should work.
val firstList: ArrayList<Int> = arrayListOf(1, 1, 1, 2, 3, 4)
val secondList: ArrayList<Int> = arrayListOf(1, 4, 5, 6, 6, 6, 7, 8)
val thirdList: ArrayList<Int> = arrayListOf(1, 6, 9)
firstList += secondList.filterNot { firstList.contains(it) }
firstList += thirdList.filterNot { firstList.contains(it) }
firstList.sort() //not sure if you want the firstList to be sorted or not
You could also make it an extension function, so then it is easier to call.
fun <T> MutableCollection<T>.addOtherNoDuplicates(vararg others: Iterable<T>){
others.forEach {other ->
this += other.filterNot { this.contains(it) }
}
}
Then the call would just be:
firstList.addOtherNoDuplicates(secondList, thirdList) //add as many as you want
firstList.sort()
If you only want to use it for ArrayList, then you can replace the MutableCollection<T> with ArrayList<T> and use the sort() directly in the function itself.
If these are very long lists, you can use a MutableSet on the side to efficiently avoid adding the unwanted values.
val input = listOf(firstList, secondList, thirdList)
val allValues = mutableSetOf<Int>()
val result = mutableListOf<Int>()
for (list in input) {
val newValues = list.filterNot { it in allValues }
result.addAll(newValues)
allValues.addAll(newValues)
}
println(result)

Removing and adding Ints from a list based on another list

Kotlin 1.4.72
I have a list of Ints called listOfSelectedIds
Another list will be generated called currentIds.
I want to be able to add or remove from the listOfSelectedIds based on the following condition:
If there is a ID from the currentIds that exists in the listOfSelectedIds then that ID should be removed from the listOfSelectedIds. Else if the ID does not exist then it should be added to the listOfSelectedids.
Is there any operators that do this on a list.
Example
listOfSelectedIds [1, 2, 3, 4, 5]
listOfCurrentIds [4, 5, 6, 7]
So the end result of listOfSelectedIds will be [1, 2, 3, 6, 7]
4 and 5 have been removed. And 6 and 7 has been added.
Many thanks in advance,
You can also do this in one iteration
fun main() {
val selectedIds = setOf(1, 2, 3, 4, 5) // Set A
val currentIds = setOf(4, 5, 6, 7) // Set B
println(selectedIds.xor(currentIds))
}
fun <T> Set<T>.xor(b: Set<T>): Set<T> {
val mutableB = b.toMutableSet()
return filterNot { mutableB.remove(it) } union mutableB
}
You can change your list to a Set and perform set operations. From a mathematical standpoint, it will be (A-B) U (B-A).
Subtract B from A, and A from B.
Do a union of the two sets generated from step 1.
fun main() {
val selectedIds = setOf(1, 2, 3, 4, 5) // Set A
val currentIds = setOf(4, 5, 6, 7) // Set B
val selectedIdsNotInCurrentIds = selectedIds subtract currentIds // Set A-B
val currentIdsNotInSelectedIds = currentIds subtract selectedIds // Set B-A
val result = selectedIdsNotInCurrentIds union currentIdsNotInSelectedIds // (A-B) U (B-A)
println(result)
}

How can I pop last repeating item from the list in Groovy?

For example:
Given list: [1, 2, 3, 4, 4, 8, 4]
Choose element, which last duplicate will be removed: 4
Output list: [1, 2, 3, 4, 4, 8]
I tried that way, but it just removes first needed element from list:
def list = [1, 2, 3, 4, 4, 8, 4]
def fruit = list.find { item -> item.equals(4)}
list.remove(fruit) //removes first matching item (one)
println list
I guess init(), last() or maybe toUnique() functions may be useful, but don't know, how to do this..
not sure if this is what you mean, but:
def list = [1, 2, 3, 4, 4, 8, 4]
def toremove = 4
list.remove(list.lastIndexOf(toremove))
assert list == [1, 2, 3, 4, 4, 8]

Is there a Groovy equivalent to Ruby's #map?

I realize there is support for #each
Book.findAll().each(){ book->
println ">>> ${book}"
}
and there's even support for #inject
def sentence = m.inject('Message: ') { s, k, v ->
s += "${k == 'likes' ? 'loves' : k} $v "
}
Is there support for #map for Groovy out of the box (without any special libraries like Functional Java)?
def list = [1,2,3,4].map{ num->
num + 1
}
assert list == [2,3,4,5]
You want collect.
groovy:000> [1,2,3,4].collect { num -> num + 1 }
===> [2, 3, 4, 5]
I hope that helps.
You can use collect, as in
[1, 2, 3, 4].collect { it + 1 }
For the case where you're calling a method directly on each object in the collection there's a shorter syntax using the spread-dot operator:
[1, 2, 3, 4]*.plus 1
(using a method Groovy adds to java.lang.Integer to implement the + operator)
This operator works even if the list contains nulls:
groovy:000> [1, 2, 3, null, 4]*.plus 1
===> [2, 3, 4, null, 5]
where with collect you'd have to check:
[1, 2, 3, null, 4].collect { it?.plus 1 }

How to select values 2+ after any number in a list?

Is there any way to select the second, third (etc) value from a value in a list in Groovy? I'm still very new to programming in general and am just wondering if there is an easy way to do this.
For example, if I have the list
[1, 2, 3, 4, 5, 6]
I want to select the next two values after each value using a for loop:
for 1: (1, 2, 3)
for 2: (2, 3, 4)
...and so on.
Is that easily possible? Thanks in advance!
If you're using groovy 1.8.1 or later, you can use the take and drop methods:
def foo = [1, 2, 3, 4, 5, 6]
foo.size().times { i ->
println foo.drop(i).take(3)
}
This will result in
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6]
[6]
If you want the iteration to stop at the last group of three, try something like this:
def foo = [1, 2, 3, 4, 5, 6]
if (foo.size() > 2) {
(foo.size() - 2).times { i ->
println foo.drop(i).take(3)
}
}
which gives
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
If you're not using Groovy 1.8.1+, then you can acheive a similar result by writing a function like so:
List split( List foo, int size ) {
(0..foo.size()-size).collect { foo[ it..it+size-1 ] }
}
Then, you can call this like:
split( [1, 2, 3, 4, 5, 6], 3 )
to print
[[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]]