How to convert list of list to simple list by removing duplicate values using scala? - list

I have following list -
List(List(
List(((groupName,group1),(tagMember,["192.168.20.30","192.168.20.20","192.168.20.21"]))),
List(((groupName,group1),(tagMember,["192.168.20.30"]))),
List(((groupName,group1),(tagMember,["192.168.20.30","192.168.20.20"])))))
I want to convert it to -
List((groupName, group1),(tagMember,["192.168.20.30","192.168.20.20","192.168.20.21"]))
I tried to use .flatten but unable to form desired output.
How do I get above mentioned output using scala??

I had to make some changes to your input to make it valid.
Input List:
val ll = List(List(
List((("groupName","group1"),("tagMember", List("192.168.20.30","192.168.20.20","192.168.20.21")))),
List((("groupName","group1"),("tagMember",List("192.168.20.30")))),
List((("groupName","group1"),("tagMember",List("192.168.20.30","192.168.20.20"))))
))
Code below works if the group, and tagMember are the same across all the elements in the list
def getUniqueIpsConstantGroupTagMember(inputList: List[List[List[((String, String), (String, List[String]))]]]) = {
// List[((String, String), (String, List[String]))]
val flattenedList = ll.flatten.flatten
if (flattenedList.size > 0) {
val group = flattenedList(0)._1
val tagMember = flattenedList(0)._2._1
val ips = flattenedList flatMap (_._2._2)
((group), (tagMember, ips.distinct))
}
else List()
}
println(getUniqueIpsConstantGroupTagMember(ll))
Output:
((groupName,group1),(tagMember,List(192.168.20.30, 192.168.20.20, 192.168.20.21)))
Now, let's assume you could have different groupNames.
Sample input:
val listWithVariableGroups = List(List(
List((("groupName","group1"),("tagMember",List("192.168.20.30","192.168.20.20","192.168.20.21")))),
List((("groupName","group1"),("tagMember",List("192.168.20.30")))),
List((("groupName","group1"),("tagMember",List("192.168.20.30","192.168.20.20")))),
List((("groupName","group2"),("tagMember",List("192.168.20.30","192.168.20.10"))))
))
The following code should work.
def getUniqueIpsForMultipleGroups(inputList: List[List[List[((String, String), (String, List[String]))]]]) = {
val flattenedList = inputList.flatten.flatten
// Map[(String, String),List[(String, List[String])]]
val groupedByGroupNameId = flattenedList.groupBy(p => p._1) map {
case (key, value) => (key, ("tagMember", extractUniqueTagIps(value)))
}
groupedByGroupNameId
}
def extractUniqueTagIps(list: List[((String, String), (String, List[String]))]) = {
val ips = list flatMap (_._2._2)
ips.distinct
}
getUniqueIpsForMultipleGroups(listWithVariableGroups).foreach(println)
Output:
((groupName,group1),(tagMember,List(192.168.20.30, 192.168.20.20, 192.168.20.21)))
((groupName,group2),(tagMember,List(192.168.20.30, 192.168.20.10)))

Related

Clickable list different intents Kotlin

I'm retrieving data to list and I need to make 2 different intents. "Activities" needs to start "e" intent and rest starts "i" intent.
binding.listview.adapter = MyAdapter(this, personArrayList)
binding.listview.isClickable = true
binding.listview.setOnItemClickListener{
parent, view, position, id ->
val name = name[position]
val activities = activities[position]
val activityTime = activityTime[position]
val description = description[position]
val imageID = imageID[position]
val i = Intent(this, DescriptionActivity::class.java)
val e = Intent(this, ProfileScreen::class.java)
i.putExtra("name", name)
i.putExtra("activityTime", activityTime)
e.putExtra("activities",activities)
i.putExtra("imageID", imageID)
i.putExtra("description", description)
startActivity(i)
}
Maybe second list is an option, but im looking to make this work in one list for now.

In Scala what is the most efficient way to remove elements in a list based on being similar to another element?

I have a long list of objects around 300, with each object in the list having this data structure:
case class MyObject(id: String,
name: String,
colour: String,
price: Int
height: Int
width: Int,
desc: String)
I can’t work out what is the best way to go through the list and for each object remove any other object that has the same name, colour, price, height and width. Note that this isn’t a simple dedupe as the ids and desc can be different. The input and output need to remain List[MyObject] and I do not know beforehand which objects are the duplicated ones.
This is my initial solution which works, but not sure its the most efficient way of doing it when it comes to dealing with large list.
def removeDuplicates(originalList: List[MyObject]): List[MyObject] = {
def loop(remaining: List[MyObject], acc: List[MyObject]): List[MyObject] = {
remaining match {
case head :: tail =>
val listOfDuplicates = tail.filter{ x =>
x.name == head.name &&
x.colour == head.colour &&
x.price == head.price &&
x.height == head.height &&
x.width == head.width
}
val deDupedTail = tail.filter(!listOfDuplicates.contains(_))
loop(deDupedTail, acc ::: listOfDuplicates)
case Nil => acc
}
}
val listOfDuplicateObjects = loop(originalList, List())
originalList.filter(!listOfDuplicateObjects.contains(_))
}
Not sure if it's most efficent, but IMHO it's elegant:
originalList.distinctBy(o => (o.name, o.colour, o.price, o.height, o.width))

Kotlin a list of random distinct numbers

I am creating a list of random numbers using the following approach
val randomList = List(4) { Random.nextInt(0, 100) }
However, this approach doesn't work as I want to avoid repetitions
One way is to shuffle a Range and take as many items as you want:
val randomList = (0..99).shuffled().take(4)
This is not so efficient if the range is big and you only need just a few numbers.In this case it's better to use a Set like this:
val s: MutableSet<Int> = mutableSetOf()
while (s.size < 4) { s.add((0..99).random()) }
val randomList = s.toList()
Create:
val list = (0 until 100).toMutableList()
val randList = mutableListOf<Int>()
for (i in 0 until 4) {
val uniqueRand = list.random()
randList.add(uniqueRand)
list.remove(uniqueRand)
}
One line approach to get a list of n distinct random elements. Random is not limited in any way.
val list = mutableSetOf<Int>().let { while (it.size() < n) it += Random.nextInt(0, 100) }.toList()

Make a new list from two other lists of different types by comparing values of each type

I have two Lists of objects that both implement an interface, but are otherwise unrelated. How can I create a new collection of objects containing only the objects of one of the lists that match a value in the other list?
Obviously I could use a for loop & do this manually, but I'd like to know how I can do this using Kotlin's standard library collection filtering functions.
So here's an example:
interface Ids
{
val id: Int
}
data class A(override val id: Int, val name: String) : Ids
data class B(override val id: Int, val timestamp: Long) : Ids
fun main(args: Array<String>) {
val a1 = A(1, "Steve")
val a2 = A(2, "Ed")
val aCol = listOf(a1, a2)
val b2 = B(2, 12345)
val b3 = B(3, 67890)
val bCol = listOf(b2, b3)
val matches = mutableListOf<B>()
// This is where I'm stuck.
// I want to filter bCol using objects from aCol as a filter.
// The result should be that matches contains only a single object: b2
// because bCol[0].id == aCol[1].id
// I'm guessing I need to start with something like this:
bCol.filterTo(matches) { ??? }
}
A straightforward approach would be to search aCol for an object with the same id for each b in bCol:
bCol.filter { b -> aCol.any { a -> a.id == b.id } }
However that may become too slow if your lists are big enough.
To make it more scalable you can first build a set of all ids in aCol:
val aColIds = aCol.map { it.id }.toSet()
And then use Set.contains method to determine whether b.id is in aColIds:
bCol.filter { it.id in aColIds }
// or equivalent
bCol.filter { aColIds.contains(it.id) }

issues when Iterate Map with list as value using groovy

def map = new HashMap<String,List<String>>()
def list = new ArrayList<String>()
def list1 = new ArrayList<String>()
list.add("hello1")
list​.add("world1")
list.add("sample1")
list.add("sample1")​​​​​​​​​​​​​​​​​​​​​​​​
list1.add("hello2")
list1.add("world2")
list1.add("sample2")
list1.add("sample2")
map.put("abc",list)
map.put("bcd",list1)
def data = new ArrayList<String>()
for(e in map){
println "key = ${e.key} value=${e.value}"
// data = "${e.value} as String[]"
data = "${e.value}"
println "size ${data.size()} " --(B)
check(data)
​}
def check(input)
{
println "${input.size()}" ---(A)
for(item in input){
print "$item "​​​​​​​​​​​​​​​​​}
​}​
I have to pass string[] to another java function from this groovy script. so I am trying to read the array list and then convert it into String array. But the problem is when I assign {e.value} to variable data and try to get the size data.size() (both step (A) and (B) ). and the size is 34. It is counting each character not the word as whole from the list. I want to iterate over each word from the list. Kindly let me know how to resolve this problem.
sample output is
key = abc value=[hello1, world1, sample1, sample1]
size 34
Here is the groovified vesion of creating the map and accessing it:
def map = [abc:['hello1', 'world1','sample1', 'sample1'], bcd:['hello2', 'world2','sample2', 'sample2']]
map.collect{ println "key: ${it.key}, list: ${it.value}, and size: ${it.value.size()}" }
Output:
key: abc, list: [hello1, world1, sample1, sample1], and size: 4
key: bcd, list: [hello2, world2, sample2, sample2], and size: 4
If you want to convert a list to an array you can just do it:
def list = ['hello1', 'world1','sample1', 'sample1']
assert list instanceof List
def array = list as String[]
assert array instanceof String[]
assert !(array instanceof List)