Related
I have a list that includes more lists (this is how it looks https://pastebin.com/BW4B9gfa). The number of lists is not constant. I need to create another list that contains only elements that are in all lists in the main list.
I made something like this as a prototype but it doesn't work:
def common_elements(list_of_lists):
lists = list_of_lists
common = lists[0].intersection(lists[1].intersection(lists[2].intersection(lists[3].intersection(lists[4].intersection(lists[5])))))
return common
I see too something like this:
A = [1,2,3,4]
B = [2,4,7,8]
commonalities = set(A) - (set(A) - set(B))
but I don't know how to use it with bigger number of lists.
You can simply do if you have a list of sets, to get a list of sets just do (lists = [set(list) for list in lists]).
lists[0].intersection(*lists)
You need to convert the first list to a set so you can use the intersection() method.
Use a loop rather than hard-coding all the indexes of the list elements.
def common_elements(lists):
if len(lists) == 0:
return []
common = set(lists[0])
for l in lists[1:]:
common = common.intersection(l)
return list(common)
using functools.reduce():
from functools import reduce
items = [[1, 2, 4], [1, 3, 4], [1, 4, 6], [1, 4, 7, 9]]
eggs = reduce(lambda x, y: set(x) & set(y), items)
print(eggs)
output:
{1, 4}
If you want to get intermediate results, you can use itertools.accumulate()
from itertools import accumulate
items = [[1, 2, 4, 5], [1, 3, 4, 5], [1, 4, 6], [1, 4, 7, 9]]
eggs = list(accumulate(items, func = lambda x, y: set(x) & set(y)))
print(eggs)
output:
[[1, 2, 4, 5], {1, 4, 5}, {1, 4}, {1, 4}]
I am working on a dictionary containing keys and values, with the keys being IDs and each value being a list. How could I check a condition like, "if there is 6 as the FIRST element of any list"?
dict_ = {0: [1, 2, 4, 1], 1: [3, 8, 4, 7], 2: [6, 2, 4, 2], 3: [5, 1, 3, 6]}
if 6 in dict_.values[0]():
print("6 is in the first cell of one of the lists")
return(True)
This looks like what I want to do but it's not the right syntax and gives me "TypeError object is not sub scriptable". I expect it to return True only if there is a 6 on the [0] of one of the lists.
You can use the built-in function any for a one-liner:
any(val[0] == 6 for val in dict.values())
Add an if val at the end for extra safety, in case any of the lists are null or empty.
Answer:
dictionary = {0: [1, 2, 4, 1], 1: [3, 8, 4, 7], 2: [6, 2, 4, 2], 3: [5, 1, 3, 6]}
for key, val in dictionary.items():
if val[0] == 6:
print("6 is present at 1 st position :", key,":",val)
Output:
6 is present at 1 st position : 2 : [6, 2, 4, 2]
First, never shadow a built-in: use d or dict_ instead of dict as a variable name. Second, note that dict.values() returns a view, you can't apply __getitem__ (or []) on a view object, let alone a method which you haven't called via parentheses.
You can modify your function and use simple iteration:
d = {0: [1, 2, 4, 1], 1: [3, 8, 4, 7], 2: [6, 2, 4, 2], 3: [5, 1, 3, 6]}
def check_value(d, val, pos=0):
for value in d.values():
if value[pos] == val:
return True
return False
res = check_value(d, 6) # True
You can also use any with a generator expression:
def check_value_any(d, val, pos=0):
return any(value[pos] == val for value in d.values())
This is lazy, i.e. if the conditional is met at any point any returns True and the function returns True. However, this may be less efficient as generators carry additional overhead.
I'm not sure what you mean but I'll try to answer you.
First of all, you iterate through dictionary like this:
for key, values in d.items():
you can also use d.keys() or d.values(), depending on what you need.
Now, if you need to see if 6 is on the first position in any list in dictionary, you can do it like this:
for key, value in d.items():
if value[0] == 6:
return True
If you want to see if number 6 appears in the first list (of the first key), you can do that with:
for value in list(d.keys())[0]:
if value == 6:
return True
Let's get the values of the dict first:
dict_ = {0: [1, 2, 4, 1], 1: [3, 8, 4, 7], 2: [6, 2, 4, 2], 3: [5, 1, 3, 6]}
for key, val in dict_.items():
print(val)
OUTPUT:
[1, 2, 4, 1]
[3, 8, 4, 7]
[6, 2, 4, 2]
[5, 1, 3, 6]
Now to check if the values (list) has a 6 on the first index:
for key, val in dict_.items(): # for each key, val (list) in the dict
if val[0] == 6: # [0] for the first index of each list
print("6 found at the first index in the list: ", val)
OUTPUT:
6 found at the first index in the list: [6, 2, 4, 2]
I have a numpy array that has different values in it some of which could be equal. I want to return a list of lists that each list contains the indices of equal elements. For example, imagine
A=np.array([2,3,2,1,1,1,3,4,5,6,6,6,6,3])
Then the result I want should be
[[0,2],[1,6,13],[3,4,5],[7],[8],[9,10,11,12]]
here is my solution but I am looking for a smarter way to do it:
h=[]
s=set()
for i in list_name:
if i in s:
continue
h.append(np.where(list_name==i))
s.add(i)
print h
Assuming the order doesn't matter, this should work.
import numpy as np
input_array = np.array([2,3,2,1,1,1,3,4,5,6,6,6,6,3])
out_array = [np.where(input_array == element)[0].tolist() for element in np.unique(input_array)]
When I run this, I get
[[3, 4, 5], [0, 2], [1, 6, 13], [7], [8], [9, 10, 11, 12]]
Try finding unique elements in the array using np.unique 1.
Loop over this array using np.where 2.
Example to find all indices with element 0 is
numpy.where(x == 0)[0]
You could use a hashmap. The key can be an int in the array, and the value can be a linked list that stores the indices of that int.
Loop through the array and for every int in the array, add its index to the hashmap.
At the end, retrieve those indices from the lists in the map.
A lookup table could do this nicely, then you can look them up explicitly:
mytable = {}
for i, value in enumerate(list_name):
mytable[value] = [i, *mytable.get(value,[])]
mytable.get(2)
[0,2]
And if you just want the indices, then:
indices = [mytable.get(a) for a in list_name]
[[0,2],[1,6,13],[3,4,5],[7],[8],[9,10,11,12]]
It's not a NumPy solution, but it does the trick (and applies to NumPy arrays too).
from collections import defaultdict
a = [2, 3, 2, 1, 1, 1, 3, 4, 5, 6, 6, 6, 6, 3]
positions = defaultdict(set)
for index, value in enumerate(a):
positions[value].add(index)
print(dict(positions))
outputs
{2: {0, 2}, 3: {1, 13, 6}, 1: {3, 4, 5}, 4: {7}, 5: {8}, 6: {9, 10, 11, 12}}
My attempt:
Kinda ugly having to do unique at the end but worked
import numpy as np
A=np.array([2,3,2,1,1,1,3,4,5,6,6,6,6,3])
def index(my_list, element):
return [i for i, x in enumerate(my_list) if x == element]
print np.unique(np.array([index(A,i) for i in A]))
>> [[0, 2] [1, 6, 13] [3, 4, 5] [7] [8] [9, 10, 11, 12]]
From this list:
N = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
I'm trying to create:
L = [[1],[2,2],[3,3,3],[4,4,4,4],[5,5,5,5,5]]
Any value which is found to be the same is grouped into it's own sublist.
Here is my attempt so far, I'm thinking I should use a while loop?
global n
n = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5] #Sorted list
l = [] #Empty list to append values to
def compare(val):
""" This function receives index values
from the n list (n[0] etc) """
global valin
valin = val
global count
count = 0
for i in xrange(len(n)):
if valin == n[count]: # If the input value i.e. n[x] == n[iteration]
temp = valin, n[count]
l.append(temp) #append the values to a new list
count +=1
else:
count +=1
for x in xrange (len(n)):
compare(n[x]) #pass the n[x] to compare function
Use itertools.groupby:
from itertools import groupby
N = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
print([list(j) for i, j in groupby(N)])
Output:
[[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5, 5]]
Side note: Prevent from using global variable when you don't need to.
Someone mentions for N=[1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 1] it will get [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5, 5], [1]]
In other words, when numbers of the list isn't in order or it is a mess list, it's not available.
So I have better answer to solve this problem.
from collections import Counter
N = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
C = Counter(N)
print [ [k,]*v for k,v in C.items()]
You can use itertools.groupby along with a list comprehension
>>> l = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]
>>> [list(v) for k,v in itertools.groupby(l)]
[[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5, 5]]
This can be assigned to the variable L as in
L = [list(v) for k,v in itertools.groupby(l)]
You're overcomplicating this.
What you want to do is: for each value, if it's the same as the last value, just append it to the list of last values; otherwise, create a new list. You can translate that English directly to Python:
new_list = []
for value in old_list:
if new_list and new_list[-1][0] == value:
new_list[-1].append(value)
else:
new_list.append([value])
There are even simpler ways to do this if you're willing to get a bit more abstract, e.g., by using the grouping functions in itertools. But this should be easy to understand.
If you really need to do this with a while loop, you can translate any for loop into a while loop like this:
for value in iterable:
do_stuff(value)
iterator = iter(iterable)
while True:
try:
value = next(iterator)
except StopIteration:
break
do_stuff(value)
Or, if you know the iterable is a sequence, you can use a slightly simpler while loop:
index = 0
while index < len(sequence):
value = sequence[index]
do_stuff(value)
index += 1
But both of these make your code less readable, less Pythonic, more complicated, less efficient, easier to get wrong, etc.
You can do that using numpy too:
import numpy as np
N = np.array([1,2,2,3,3,3,4,4,4,4,5,5,5,5,5])
counter = np.arange(1, np.alen(N))
L = np.split(N, counter[N[1:]!=N[:-1]])
The advantage of this method is when you have another list which is related to N and you want to split it in the same way.
Another slightly different solution that doesn't rely on itertools:
#!/usr/bin/env python
def group(items):
"""
groups a sorted list of integers into sublists based on the integer key
"""
if len(items) == 0:
return []
grouped_items = []
prev_item, rest_items = items[0], items[1:]
subgroup = [prev_item]
for item in rest_items:
if item != prev_item:
grouped_items.append(subgroup)
subgroup = []
subgroup.append(item)
prev_item = item
grouped_items.append(subgroup)
return grouped_items
print group([1,2,2,3,3,3,4,4,4,4,5,5,5,5,5])
# [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5, 5]]
I have two lists that i need to combine where the second list has any duplicates of the first list ignored. .. A bit hard to explain, so let me show an example of what the code looks like, and what i want as a result.
first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]
# The result of combining the two lists should result in this list:
resulting_list = [1, 2, 2, 5, 7, 9]
You'll notice that the result has the first list, including its two "2" values, but the fact that second_list also has an additional 2 and 5 value is not added to the first list.
Normally for something like this i would use sets, but a set on first_list would purge the duplicate values it already has. So i'm simply wondering what the best/fastest way to achieve this desired combination.
Thanks.
You need to append to the first list those elements of the second list that aren't in the first - sets are the easiest way of determining which elements they are, like this:
first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]
in_first = set(first_list)
in_second = set(second_list)
in_second_but_not_in_first = in_second - in_first
result = first_list + list(in_second_but_not_in_first)
print(result) # Prints [1, 2, 2, 5, 9, 7]
Or if you prefer one-liners 8-)
print(first_list + list(set(second_list) - set(first_list)))
resulting_list = list(first_list)
resulting_list.extend(x for x in second_list if x not in resulting_list)
You can use sets:
first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]
resultList= list(set(first_list) | set(second_list))
print(resultList)
# Results in : resultList = [1,2,5,7,9]
first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]
print( set( first_list + second_list ) )
You can bring this down to one single line of code if you use numpy:
a = [1,2,3,4,5,6,7]
b = [2,4,7,8,9,10,11,12]
sorted(np.unique(a+b))
>>> [1,2,3,4,5,6,7,8,9,10,11,12]
Simplest to me is:
first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]
merged_list = list(set(first_list+second_list))
print(merged_list)
#prints [1, 2, 5, 7, 9]
resulting_list = first_list + [i for i in second_list if i not in first_list]
You can also combine RichieHindle's and Ned Batchelder's responses for an average-case O(m+n) algorithm that preserves order:
first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]
fs = set(first_list)
resulting_list = first_list + [x for x in second_list if x not in fs]
assert(resulting_list == [1, 2, 2, 5, 7, 9])
Note that x in s has a worst-case complexity of O(m), so the worst-case complexity of this code is still O(m*n).
Based on the recipe :
resulting_list = list(set().union(first_list, second_list))
you can use dict.fromkeys to return a list with no duplicates:
def mergeTwoListNoDuplicates(list1, list2):
"""
Merges two lists together without duplicates
:param list1:
:param list2:
:return:
"""
merged_list = list1 + list2
merged_list = list(dict.fromkeys(merged_list))
return merged_list
This might help
def union(a,b):
for e in b:
if e not in a:
a.append(e)
The union function merges the second list into first, with out duplicating an element of a, if it's already in a. Similar to set union operator. This function does not change b. If a=[1,2,3] b=[2,3,4]. After union(a,b) makes a=[1,2,3,4] and b=[2,3,4]
first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]
newList=[]
for i in first_list:
newList.append(i)
for z in second_list:
if z not in newList:
newList.append(z)
newList.sort()
print newList
[1, 2, 2, 5, 7, 9]