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)
Related
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)
}
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();
It's a common problem here, but I couldn't find any simplified methods for Dart in particular - how can I convert a list like this
[1, 2, 3, 4, 5, 6]
into a list like this
[[1, 2], [3,4], [5,6]]
assuming there are no extra elements after this?
Dart Quiver package is a set of utility libraries for Dart that makes using many Dart libraries easier and more convenient or adds additional functionality (https://github.com/google/quiver-dart).
You can use the partition function from quiver iterables library as follows.
import 'package:quiver/iterables.dart';
main() {
var list = [1, 2, 3, 4, 5, 6];
# Use partition function to segment lists into chunks of size 2
var newList = partition<int>(list, 2);
print (newList);
}
Result [[1, 2], [3,4], [5,6]]
var list = [1, 2, 3, 4];
List<int> temp = [];
List<List<int>> newList = list.fold<List<List<int>>>([], (newList, i) {
if (temp.length < 2) {
temp.add(i);
}
if (temp.length >= 2) {
List<int> newValue = new List<int>.from(temp);
newList.add(newValue);
temp.clear();
}
return newList;
});
print(newList);
How can I remove all occurrences of a sublist from a list, eg
List(1, 2, 3, 4, 5, 6, 7, 4, 8, 9, 10, 5).removeSubList(4, 5)
should remove all occurrences of (4, 5) (in this order!), so it returns
List(1, 2, 3, 6, 7, 4, 8, 9, 10, 5)
A recursive solution using indexOfSlice:
def removeSubList(l: List[Int], sublist: List[Int]): List[Int] = l.indexOfSlice(sublist) match {
case -1 => l
case index => removeSubList(l.patch(index, Nil, sublist.length), sublist)
}
// all of these print List(1 ,2 ,3):
println(removeSubList(List(1,2,3), List(4,5)))
println(removeSubList(List(1,2,3,4,5), List(4,5)))
println(removeSubList(List(4,5,1,2,3), List(4,5)))
println(removeSubList(List(4,5,1,2,4,5,3), List(4,5)))
EDITED:
(thanks #corvus_192) reverting to using indexOfSlice version instead of using diff, which ignores sublist order.
(thanks #The Archetypal Paul) using patch for cleaner removal of sublist
Using Tzach Zohar idea with different implementation:
def removeSubList[T](list: List[T], sublist: List[T]): List[T] =
if (list.containsSlice(sublist))
removeSubList(list.diff(sublist), sublist)
else list
Variant on Tzach Zohar idea but with the assumption the OP wants a result that does not include the given sublist ever. Handles the case when sublist is empty
/**
* Return `s` with no occurrence of `target` present
*
* #param s
* #param target
* #return The sequence free of any occurrence of the target slice
*/
def removeCompletely[E](s: Seq[E], target: Seq[E]): Seq[E] = {
if (s.isEmpty || target.isEmpty)
s
else
removeCompletely0(s, target)
}
private def removeCompletely0[E](s: Seq[E], target: Seq[E]): Seq[E] = {
val sliceIdx = s.indexOfSlice(target)
if (sliceIdx >= 0) {
val patched = s.patch(sliceIdx, s take 0, target.size)
removeCompletely0(patched, target)
}
else {
s
}
}
I have a List
val family=List("1","2","11","12","21","22","31","33","41","44","51","55")
i want to take its first n elements but the problem is that parents size is not fixed.
val familliar=List("1","2","11") //n=3
You can use take
scala> val list = List(1,2,3,4,5,6,7,8,9)
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> list.take(3)
res0: List[Int] = List(1, 2, 3)
List(1,2,3).take(100) //List(1,2,3)
The signature of take will compare the argument with index, so the incremental index will never more than argument
The signature of take
override def take(n: Int): List[A] = {
val b = new ListBuffer[A]
var i = 0
var these = this
while (!these.isEmpty && i < n) {
i += 1
b += these.head
these = these.tail
}
if (these.isEmpty) this
else b.toList
}
Use take:
val familliar = family.take(3)