How to remove Duplicate Values from a list in groovy - groovy

I have a collection of ID list to be saved into the database
if(!session.ids)
session.ids = []
session.ids.add(params.id)
and I found out that list has duplicates, like
[1, 2, 4, 9, 7, 10, 8, 6, 6, 5]
Then I wanted to remove all duplicates by applying something like :
session.ids.removeAll{ //some clousure case }
I found only this:
http://groovy.codehaus.org/groovy-jdk/java/util/Collection.html

I am not a Groovy person , but I believe you can do something like this :
[1, 2, 4, 9, 7, 10, 8, 6, 6, 5].unique { a, b -> a <=> b }
Have you tried session.ids.unique() ?

How about:
session.ids = session.ids.unique( false )
Update
Differentiation between unique() and unique(false) : the second one does not modify the original list.
def originalList = [1, 2, 4, 9, 7, 10, 8, 6, 6, 5]
//Mutate the original list
def newUniqueList = originalList.unique()
assert newUniqueList == [1, 2, 4, 9, 7, 10, 8, 6, 5]
assert originalList == [1, 2, 4, 9, 7, 10, 8, 6, 5]
//Add duplicate items to the original list again
originalList << 2 << 4 << 10
// We added 2 to originalList, and they are in newUniqueList too! This is because
// they are the SAME list (we mutated the originalList, and set newUniqueList to
// represent the same object.
assert originalList == newUniqueList
//Do not mutate the original list
def secondUniqueList = originalList.unique( false )
assert secondUniqueList == [1, 2, 4, 9, 7, 10, 8, 6, 5]
assert originalList == [1, 2, 4, 9, 7, 10, 8, 6, 5, 2, 4, 10]

Use unique
def list = ["a", "b", "c", "a", "b", "c"]
println list.unique()
This will print
[a, b, c]

def unique = myList as Set
Converts myList to a Set. When you use complex (self-defined classes) make sure you have thought about implementing hashCode() and equals() correctly.

If it is intended that session.ids contain unique ids, then you could do:
if(!session.ids)
session.ids = [] as Set
Then when you do:
session.ids.add(params.id)
duplicates will not be added.
Also you can use this syntax:
session.ids << params.id

Merge two arrays and make elements unique:
def arr1 = [1,2,3,4]
def arr2 = [1,2,5,6,7,8]
def arr3 = [1,5,6,8,9]
Let's look at mergings:
arr1.addAll(arr2, arr3)
// [1, 2, 3, 4, [1, 2, 5, 6, 7, 8], [1, 5, 6, 8, 9]]
def combined = arr1.flatten()
// [1, 2, 3, 4, 1, 2, 5, 6, 7, 8, 1, 5, 6, 8, 9]
def combined = arr1.flatten().unique()
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
def combined = (arr1 + arr2 + arr3).flatten().unique()
def combined = (arr1 << arr2 << arr3).flatten().unique()
def combined = arr1.plus(arr2).plus(arr3).flatten().unique()
Output will be:
println combined
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Related

Apply if statement on multiple lists with multiple conditions

I would like to append ids to a list which meet a specific condition.
output = []
areac = [4, 4, 4, 4, 1, 6, 7,8,9,6, 10, 11]
arean = [1, 1, 1, 4, 5, 6, 7,8,9,10, 10, 10]
id = [1, 2, 3, 4, 5, 6, 7,8,9,10, 11, 12]
dist = [2, 2, 2, 4, 5, 6, 7.2,5,5,5, 8.5, 9.1]
for a,b,c,d in zip(areac,arean,id,dist):
if a >= 5 and b==b and d >= 3:
output.append(c)
print(comp)
else:
pass
The condition is the following:
- areacount has to be >= 5
- At least 3 ids with a distance of >= 3 with the same area_number
So the id output should be [10,11,12].I already tried a different attempt with Counter that didn't work out. Thanks for your help!
Here you go:
I changed the list names to something more descriptive.
output = []
area_counts = [4, 4, 4, 4, 1, 6, 7, 8, 9, 6, 10, 11]
area_numbers = [1, 1, 1, 4, 5, 6, 7, 8, 9, 10, 10, 10]
ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
distances = [2, 2, 2, 4, 5, 6, 7.2, 5, 5, 5, 8.5, 9.1]
temp_numbers, temp_ids = [], []
for count, number, id, distance in zip(counts, numbers, ids, distances):
if count >= 5 and distance >= 3:
temp_numbers.append(number)
temp_ids.append(id)
for (number, id) in zip(temp_numbers, temp_ids):
if temp_numbers.count(number) == 3:
output.append(id)
output will be:
[10, 11, 12]

When i use set( list_a + list_b ) it returns a dictionary. Do sets naturally return dictionaries?

I'm doing some beginner python exercises and one of them is to remove duplicates from a list. I've successfully done it, but the strange thing is that it is returning a dictionary instead of a list.
This is my code.
import random
a = []
b = []
for i in range(0,20):
n = random.randint(0,10)
a.append(n)
for i in range(0,20):
n = random.randint(0,10)
b.append(n)
print(sorted(a))
print(sorted(b))
c = set(list(a+b))
print(c)
and this is what it's spitting out
[0, 0, 1, 1, 1, 1, 2, 3, 4, 4, 6, 6, 7, 7, 7, 8, 9, 9, 10, 10]
[0, 1, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 7, 8, 9, 9, 10, 10, 10]
{0, 1, 2, 3, 4, 6, 7, 8, 9, 10}
thanks in advance!
{0, 1, 2, 3, 4, 6, 7, 8, 9, 10} is a set, not a dictionary, a dictionary would be printed as {key:value, key:value, ...}
Try print(type(c)) and you'll see it prints <class 'set'> rather than <class 'dict'>
Also try the following
s = {1,2,3}
print(type(s))
d = {'a':1,'b':2,'c':3}
print(type(d))
You'll see the type is different

Appending an int key in a dictionary

I am trying to create a dictionary from the following lists:
link_i = [1, 1, 3, 3, 3, 4, 4, 5, 5, 6]
link_j = [2, 3, 1, 2, 5, 5, 6, 6, 4, 4]
link_i = [1, 1, 3, 3, 3, 4, 4, 5, 5, 6]
link_j = [2, 3, 1, 2, 5, 5, 6, 6, 4, 4]
nodes = [1, 2, 3, 4, 5, 6]
# Creating a dictionary containing nodes and their incoming links:
out_dict = {}
for i in nodes:
for j in range(0,len(link_i)):
if (link_i[j] == i):
if i not in out_dict:
out_dict[i] = link_j[j]
elif i in out_dict:
out_dict[i].append(link_j[j])
However, I am not able to append the key since it has the type int. I get the error:
line 21, in <module>
out_dict[i].append(link_j[j])
AttributeError: 'int' object has no attribute 'append'
I am trying to get the output as:
{1: [2, 3], 3: [1, 2, 5], 4: [5, 6], 5: [6, 4], 6: [4]}
To keep the code simple you can use a dict comprehension and set the default value for each node to empty list. With that you don't need to check if the node is already part of the dict and you can just append the links.
link_i = [1, 1, 3, 3, 3, 4, 4, 5, 5, 6]
link_j = [2, 3, 1, 2, 5, 5, 6, 6, 4, 4]
nodes = [1, 2, 3, 4, 5, 6]
# Creating a dictionary containing nodes and their incoming links:
# fill the dict with empty lists for each node
out_dict = {node: [] for node in nodes}
for i in nodes:
for j in range(0,len(link_i)):
if (link_i[j] == i):
# append link to the list for the node
out_dict[i].append(link_j[j])
The output then looks like this:
{1: [2, 3], 2: [], 3: [1, 2, 5], 4: [5, 6], 5: [6, 4], 6: [4]}
You need to change:
if i not in out_dict:
out_dict[i] = link_j[j]
to
if i not in out_dict:
out_dict[i] = [link_j[j]]
This is because after you first add key "i" to out_dict, you are assigning it a single value which is of type int. In order to be able to add to this, later on, it needs to be a mutatable data type such as a list which does have attribute append. This doesn't fix all your problems because even with this change you still don't get your desired output but it will allow you to debug further.

Finding elements in specific index between two lists using a function or other

How do I define a function where for a and b it would return 7 and 5
or a[0] and b[0] and a[4] and b[4]. The problem is the length of both lists could change at any time...
I've tried:
if a[0]== b[0]:
print(a[0])
but if the length of lists changes then it would eventually return a list Index out of range error.
Any help is much appreciated.
a = [7, 5, 9, 3, 5, 3, 6, 7, 8, 4, 3, 3, 4, 5]
b = [7, 3, 3, 5, 5, 2, 1, 5, 2, 5, 2, 9, 8, 6]
Zip two lizts with zip and iterate over it:
a = [7, 5, 9, 3, 5, 3, 6, 7, 8, 4, 3, 3, 4, 5]
b = [7, 3, 3, 5, 5, 2, 1, 5, 2, 5, 2, 9, 8, 6]
for a_i, b_i in zip(a, b):
if a_i == b_i:
print(a_i, b_i)
Out:
7, 7
5, 5
or define it as a fiunction:
def extract_matches(a, b):
result = []
for a_i, b_i in zip(a, b):
if a_i == b_i:
result.append((a_i, b_i))
return result
matches = extract_matches(a, b)
matches
Out:
[(7, 7), (5, 5)]
How the zip works. zip function always zips lists by shorter. It returns a generator, so you should iterate it:
list(zip([1,2,3], [1,2]))
Out:
[(1, 2), (1, 2)] # list of pairs
list(zip([], [1,2,3]))
Out:
[] # length of shorter is 0, so you get zero length list

Creating all the possible combinations inside an element of list

I need to explore every permutations of a list. Let's say I have this initiated variable:
samplelist = [1, 2, 3, 4, 5, 6, 7, 8, 9]
An example output would be:
output = [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 3, 2, 4, 5, 6, 7, 8, 9], [1, 3, 4, 2, 5, 6, 7, 8, 9], [1, 3, 5, 3, 2, 6, 7, 8, 9]] .... and so on.
Here's what I did:
import itertools
samplelist = [1, 2, 3, 4, 5, 6, 7, 8, 9]
def combinations(iterable, r):
pool = tuple(iterable)
n = len(pool)
if r > n:
return
indices = range(r)
yield tuple(pool[i] for i in indices)
while True:
for i in reversed(range(r)):
if indices[i] != i + n - r:
break
else:
return
indices[i] += 1
for j in range(i+1, r):
indices[j] = indices[j-1] + 1
yield tuple(pool[i] for i in indices)
list(combinations_with_replacement(samplelist, 9))
Since the length of the list is 9, the factorial of 9 is 362,880. I'm trying to get all these combinations of the elements in the list
But my output is not what I'm trying to achieve.
itertools.permutations(samplelist) returns the 9! lists

Resources