How to manipulate and compare lists using Groovy - list

I have 3 lists that I need to compare and manipulate. Here are the lists, for example:
def list1 = ['abc', '123','789'];
def list2 = ['456', 'abc', '123'];
def list3 = ['mil', 'len', 'nium'];
I need to compare values of list1 and list2 and if they are the same, I need to return the corresponding item with the same index of list1 found in list3.
Using the example above, since list1[0] and list2[1] are the same, I need to return the list3 value, 'mil'.
The lists' value will also be dynamic so how will I be able to do it in groovy?

You can read about it on Groovy Docs. You can find common elements by
def commons = collection1.intersect(collection2)
and find element in third list using index from first list by indexOf.
It may be useful as well Comparing lists
Something like
def commons = list1.intersect(list2)
def indexes = []
commons.each {
indexes << list1.indexOf(it)
}
def values = []
indexes.each {
values << list3[it]
}
Of course it can be done in many ways, easier, but it works too in some cases

Related

Groovy: Compare lists ignoring the order of elements in them

I have two lists, let's say:
def list1 = ["ABC", "DEF", "GHI", "JKL"]
def list2 = ["ABC", "DEF", "JKL", "GHI"]
I want to compare these two lists and make sure that the values they have are the same, despite the order in which they appear.
I've tried this but it doesn't seem to work:
assert new HashSet( Arrays.asList(list1)).equals(new HashSet( Arrays.asList(list2)))
Could anyone point me in the right direction?
Much appreciated.
If you want to stay with Lists and not use Sets, you can compare sorted lists:
def list1 = ["ABC", "DEF", "GHI", "JKL"]
def list2 = ["ABC", "DEF", "JKL", "GHI"]
assert list1 != list2
assert list1.sort() == list2.sort()
The suggested Set-based comparison might be dangerous, it the lists contain different numbers of duplicates:
def list1 = ["ABC"]
def list2 = ["ABC", "ABC", "ABC"]
assert list1.sort() != list2.sort()
assert list1 as Set == list2 as Set // GOTCHA!
Your comparison is not working because you're comparing sets of lists.
new HashSet(Arrays.asList()) creates a HashSet<List<String>> (roughly), and when Set equality is being checked, the element-wise comparison calls the usual List.equals, which doesn't work because order matters in lists.
Your lists should make flat elements in target sets for it to work based on Set comparison logic (such that you compare instances of HashSet<String> instead of HashSet<List<String>>). Your code should be
new HashSet(list1).equals(new HashSet(list2))

Need to combine two list in scala with some condition for replacement

I want to do this :
val list1 = List(Student("ivan","history",45))
val list2 = List(Student("ivan","history",40),Student("alexander","physics",81),Student("vlad","math",70))
I want to combine list1 and list2 so that list1's element remove list's 2 element based on student name and subject.
Required Output :
List(Student("ivan","history",45),Student("alexander","physics",81),Student("vlad","math",70))
I would go for a groupBy here. You concatenate the two lists, then you groupBy and take the head element for each key. This will scrumble the order among students though, but is efficient.
(list1 ++ list2)
.groupBy(s => (s.name, s.subject))
.map { case (key, values) =>
values.head
}
You can define a function to check if two Student values match:
def isSame(s: Student, t: Student): Boolean = (s.name == t.name && s.sub == t.sub)
Using this you can iterate over list2 and check if there is a match in list1. If there is, you use the value from list1 else keep the value from list2.
list2.map(s2 => (list1.map(s1 => if (isSame(s1, s2)) s1 else s2))).flatten
Note that this might not be the most optimal solution if the two lists are huge.

How to check if unordered lists have exactly the same elements without using python methods. (need to use loops). In python

list1 = ['a','b','c','d']
list2 = ['b','c','d','a']
I have these two unordered lists and want to check if both have EXACTLY the same elements. Don't want to use set() or sorted() methods. But use looping to loop through both lists.
Keep it simple, without any helper function or list comprehension:
list1 = ['a','b','c','d']
list2 = ['b','c','d','a']
def same_lists(li1, li2):
if len(li1) != len(li2): # if the length of the lists is different than they are not equal so return false
return False
else:
for item1 in li1:
if item1 not in li2:
return False # if there is one item in li1 that is not in li2 than the lists are not identical so return false
for item2 in li2:
if item2 not in li1:
return False # same as three rows up
return True # if we didn't returned false for the whole list, than the lists are identical and we can return true.
print (same_lists(list1,list2))
This should work:
common_elements = [x for x in list1 if x in list2]
if len(list1) == len(list2) == len(common_elements):
print("EXACT SAME ELEMENTS")
else:
print("DIFFERENT ELEMENTS")
If you sort the elements first, or keep track as you encounter them, e.g. in another container, you can hand roll some solutions.
If you insist on avoiding this you need to check everything in the first list is in the seocnd and vice versa.
def same_lists(li1, li2):
if len(li1) != len(li2):
return False
else:
for item in li1:
if item not in li2:
return False
for item in li2:
if item not in li1:
return False
return True
This returns True for list1 = ['a','b','c','d'] compared with list2 = ['b','c','d','a'] and False for list3 = ['b','c','d','a', 'a'] and list4 = ['b','c','d','a', 'z'].
This is quadratic - we've compared everything with everything else (with a small optimisation checking the lengths first). We have to go through BOTH lists comaparing with the other list.
It would be quicker to sort first.

Find an element in an irregular list in python

I have the following class
class A:
def __init__(self, elements):
self.elements = elements
I need to write a function that takes two instances of it, and finds if instance 1 is in the elements of instance 2. This is an irregular list, because those elements contain more instances of A to an arbitrary depth.
I want something along those lines:
def is_element_in(instanceA1, instanceA2):
found = False
for inherit in instanceA2.instanceof.inherits:
if instanceA1 == inherit:
found = True
else:
n_inherit(instanceA1, inherit)
return found
What's the best way to write this? I read some answers about flattening the list. I don't know if it's the best idea here, because I have to access fields to get my list of elements. Any python libraries that can be used here?
A possible solution is
def is_element_in(items, element):
for item in items:
if item == element:
return True
if isinstance(item, list) and is_element_in(item, element):
return True
return False
items = [[1, 2], [3], [[4], 5]]
print(is_element_in(items, 4))
print(is_element_in(items, 0))
Prints
True
False

how to find whether this python list within list contains duplicates or not?

I have the following python list :-
a=[['t1', ['a', 'c']], ['t2', ['b']], ['t2', ['b']]]
now it contains duplicate lists within it ['t2', ['b']] 2 times
I want to return true if the list contains duplicates.
Can anyone please help me how to do so ?
I tried to use the set function but it is not working here !
If you are free to represent your list a as a list of tuples/records:
b = [(item[0], tuple(item[1])) for item in a]
(or, in the first place):
a = [('t1', ('a', 'c')), ('t2', ('b')), ('t2', ('b'))]
Then the items become hashable and you can use collections.Counter:
from collections import Counter
c = Counter(b)
So you can find duplicates like:
duplicated_items = [key for key, count in c.iteritems() if count > 1]
(Or you can use set):
has_duplicates = len(set(b)) < len(b)
If your aim is to remove duplicates, this answer might be helpful:
unique_a = [i for n, i in enumerate(a) if i not in a[:n]]
You can rewrite it this way:
has_duplicates = lambda l: True in [(i in l[:n]) for n, i in enumerate(l)]
You can call it this way:
has_duplicates(a) # True