Related
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]
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
I have a list containing sub-lists. If the differences between sub-lists are less than 0.1, I want to group these sub-lists.
import numpy as np
def difference(A, B):
difference = []
zip_object = zip(sorted(A), sorted(B))
for l1, l2 in zip_object:
difference.append(abs(l1-l2))
sum_ = 0
for i in difference:
sum_ += i
if round(sum_, 5) <=0.1:
return True
return False
aaa = [[1.001, 2, 5, 3, 5, 4, 6, 9, 10],
[2, 5, 3, 5, 4, 6.001, 9, 10, 1],
[2, 5.5, 3, 5, 4, 6.001, 9, 10, 1],
[2, 5.5, 3, 5, 4, 6.001, 9, 10.2, 1],
[2, 5, 2.999, 5, 4, 6.001, 9, 10, 1],
[2, 5.5, 2.999, 5, 4, 6.001, 9, 10.2, 1]]
AAA = []
for i in range(len(aaa)):
a = [i]
for j in range(len(aaa)):
if i < j and difference(aaa[i], aaa[j])==True:
a.append(j)
AAA.append(a)
print(AAA)
My code yields:
[[0, 1, 4], [1, 4], [2], [3, 5], [4], [5]]
But I want the result like this
[[0, 1, 4], [3, 5]]
As long as you can import numpy, here is a short solution that uses numpy
import numpy as np
aaa = [[1.001, 2, 5, 3, 5, 4, 6, 9, 10],
[2, 5, 3, 5, 4, 6.001, 9, 10, 1],
[2, 5.5, 3, 5, 4, 6.001, 9, 10, 1],
[2, 5.5, 3, 5, 4, 6.001, 9, 10.2, 1],
[2, 5, 2.999, 5, 4, 6.001, 9, 10, 1],
[2, 5.5, 2.999, 5, 4, 6.001, 9, 10.2, 1]]
# sort each row for calculating differences
aaa = np.sort(aaa,axis=1)
# calculate the difference
diff = np.sum(np.abs(aaa[:,None,:] - aaa),axis=2)
# don't need an item with itself
np.fill_diagonal(diff,1e5)
# find the pairs of rows that have a small difference
locs = np.unique(np.sort(np.where(diff <= .1 ),axis=0),axis=1).T
# get the results
res = {}
redundant = []
flattened_list = []
for pair in locs:
if pair[0] not in res.keys() and pair[0] not in redundant:
res[pair[0]] = [pair[1]]
redundant.extend(pair)
elif pair[0] in res.keys():
if pair[1] not in res[pair[0]]:
res[pair[0]].append(pair[1])
flattened_list = [[key,*val] for key,val in res.items()]
I've created a verbose program that you can adjust to your needs.
def new_difference(list1, list2):
list_length = len(list1)
list1 = sorted(list1)
list2 = sorted(list2)
total = 0
for i in range(list_length):
total += abs(list1[i] - list2[i])
return round(total, 5) <= 0.1;
def add_good_diff():
# if 0 matches with 1, create dictionary 0: [1]
# if 0 matches with 4, add to the list like so 0: [1, 4]
if not i in good_diff:
good_diff[i] = [j]
else:
good_diff[i].append(j)
def proceed_with_diff(i, j):
# let's say 0'th list matches with 1 and 4
# when we get to the next list, we don't want to compare 1 and 4
# so, check each list in good_diff. If found, return False
# which means, skip matching i and j
for item in good_diff:
if i in good_diff[item] and j in good_diff[item]:
print(f"{i} and {j} already diff'ed successfully")
return False
return True
aaa = [[1.001, 2, 5, 3, 5, 4, 6, 9, 10],
[2, 5, 3, 5, 4, 6.001, 9, 10, 1],
[2, 5.5, 3, 5, 4, 6.001, 9, 10, 1],
[2, 5.5, 3, 5, 4, 6.001, 9, 10.2, 1],
[2, 5, 2.999, 5, 4, 6.001, 9, 10, 1],
[2, 5.5, 2.999, 5, 4, 6.001, 9, 10.2, 1]]
sets = len(aaa)
good_diff = {} # stores {0: {1, 4}, 3: {5}} - successful matches
final_list = [] # is used to flatten output to [[0, 1, 4], [3, 5]]
# starts with 0'th item
for i in range(0, sets):
# compares 0'th item with 1..5
for j in range(i+1, sets):
print(f'Matching {i} and {j}')
# if i and j have been compared already, don't compare them again
# proceed_with_diff returns True a match has not been done before
if proceed_with_diff(i, j):
# if diff is within accepted value, add it to the dictionary
if new_difference(aaa[i], aaa[j]):
print(f'{i} matches {j}. Adding to good_diff')
add_good_diff()
# flatten the dictionary
# {0: [1, 4]} will become [0, 1, 4]
for item in good_diff:
final_list.append([item] + good_diff[item])
print(final_list)
When you run that, you will see the result:
[[0, 1, 4], [3, 5]]
Give it a shot.
This question already has answers here:
Print an element in a list based on a condition
(3 answers)
Select value from list of tuples where condition
(4 answers)
How to return a subset of a list that matches a condition [duplicate]
(1 answer)
Closed 3 years ago.
I have a list with 22 integers (ranging from 1 through 9) and want to create/ print a new list containing only those integers that are above 5.
This is what I have tried so far - the result (obviously) is that 'the_list' gets printed multiple times - i.e. the number of times = the number of instances above 5.
the_list = [1, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7]
print(the_list)
k=5
tl2=[]
for i in the_list:
if i > k :
tl2.append(the_list)
Try this code:
>>> the_list = [1, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7]
>>> print(the_list)
[1, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7]
>>> the_filtered_list = list(filter(lambda x: x > 5, the_list))
>>> print(the_filtered_list)
[7, 6, 6, 7, 6, 6, 7]
See
filter
lambda
EDIT:
Another option is to use a generator expression:
>>> the_filtered_list = list(i for i in the_list if i > 5)
>>> print(the_filtered_list)
[7, 6, 6, 7, 6, 6, 7]
See
generator expressions and list comprehensions
EDIT:
My initial answer was indeed slow and memory inefficient. Here is the comparison of several possibilities. Which one to choose depends on how big the list is and what it is used for later.
>>> import random
>>> import timeit
>>> import sys
>>>
>>> the_list = [random.randrange(1, 10) for _ in range(100)]
>>>
>>> timeit.timeit('filter(lambda x: x > 5, the_list)', setup=f'the_list = {the_list}')
0.15890196000000856
>>> timeit.timeit('[i for i in the_list if i > 5]', setup=f'the_list = {the_list}')
2.633208761999981
>>> timeit.timeit('(i for i in the_list if i > 5)', setup=f'the_list = {the_list}')
0.227755295999998
>>>
>>> timeit.timeit('list(filter(lambda x: x > 5, the_list))', setup=f'the_list = {the_list}')
7.5565902380000125
>>> timeit.timeit('list(i for i in the_list if i > 5)', setup=f'the_list = {the_list}')
3.599053368
>>>
>>> sys.getsizeof(filter(lambda x: x > 5, the_list))
64
>>> sys.getsizeof([i for i in the_list if i > 5])
440
>>> sys.getsizeof((i for i in the_list if i > 5))
128
>>>
>>> sys.getsizeof(list(filter(lambda x: x > 5, the_list)))
480
>>> sys.getsizeof(list(i for i in the_list if i > 5))
480
The problem is you are appending the list, not the number 'i'
the_list = [1, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7]
print(the_list)
k=5
tl2=[]
# the_list refers to the entire list
# i is an element in the list
for i in the_list:
if i > k :
# append the number 'i' if it is greater than k
tl2.append(i)
print (t12)
the_list = [1, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 3, 4, 5, 6, 7]
print(the_list)
k=5
new_ls = [x for x in the_list if x >k]
print(new_ls)
try this solution
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