Find all occurences of an element in a matrix in Python - python

I have a list of lists and I want to find the cordinates of all occurences. I managed to do it, but I wonder if there is a better way to do it using numpy where for example.
This is what I did:
my_list = [[1,2,3,1, 3], [1,3,2]]
target_value = 3
locations = []
for k in range(len(my_list)):
indices = [i for i, x in enumerate(my_list[k]) if x == target_value]
locations.append((k, indices))
locations2 = []
for row in locations:
for i in row[1]:
locations2.append((row[0], i))
print locations2 # prints [(0, 2), (0, 4), (1, 1)]

While you could get this to work in numpy, numpy isn't all that happy with ragged arrays. I think the pure python comprehension version looks okay:
>>> my_list = [[1,2,3,1, 3], [1,3,2]]
>>> [(i,j) for i,x in enumerate(my_list) for j,y in enumerate(x) if y == 3]
[(0, 2), (0, 4), (1, 1)]

Related

Return the index of the common elements of two lists

So I have two lists:
The output only considers 1 and not 0
lst1 = [1,0,0,1,1]
lst2 = [0,0,1,1,0]
And the output is:
[3] # because the index where the elements are the same is at index 3
How should I code this?
The way I coded this was I tried having two loops
lst1 = [1,0,0,1,1]
lst2 = [0,0,1,1,0]
my_list = []
for i in range(len(lst1)):
for i in range(len(lst2)):
if lst1[i] == lst2[i] == 1:
my_list.append(lst1[i])
print(my_list)
try this:
lst1 = [1,0,0,1,1]
lst2 = [0,0,1,1,0]
[idx for idx, (f,s) in enumerate(zip(lst1,lst2)) if f==s]
#[1,3]
Edit: base on your comment. zip concatenate element by element of two list. see this example:
a = [1,2,4,6,8]
b = [0,3,5,7,9]
list(zip(a,b))
# [(1, 0), (2, 3), (4, 5), (6, 7), (8, 9)]
out=[]
for i, x, y in enumerate (zip(lst1,lst2)):
if x==y:
out.append(i)
The below is what you are looking for. The idea is to loop over the 2 lists and add to the results the index of the matching entries. An implicit assumption is that the 2 lists got same length.
result = [idx for idx,_ in enumerate(lst1) if lst1[idx] == lst2[idx]]
output
[1, 3]

Making number from elements of list

How can i check that can i create a number from elements of list?
For example:
list=[1,1,3,3,3,3,5,10,23,53]
And now we can make 9 from [1,3,5] or [3,3,3]
i tried something like that:
list=[1,1,3,3,3,3,5,10,23,53]
tmp=[]
sum=0
for i in range(len(list)):
tmpChange=9
tmpChange -= list[i]+sum
if tmpChange == 0:
break
elif tmpChange > 0:
tmp.append(list[i])
sum += list[i]
print(tmpChange)
print(tmp)
else:
tmp.pop(i)
A naive way to approach this is to find all of the subsets of your original list, which you can do using itertools.combinations. Then you can check if the subset sums to your original value, then add them to a set.
import itertools
l = [1,1,3,3,3,3,5,10,23,53]
total = 9
values = set()
for r in range(1, len(l)):
for c in itertools.combinations(l, r):
if sum(c) == total:
values.add(tuple(c))
The result is then
>>> values
{(1, 3, 5), (3, 3, 3)}
As another example using the following data
l = [1,1,3,3,3,3,4,5,9,10,23,53]
The result would be
>>> values
{(4, 5), (3, 3, 3), (1, 1, 3, 4), (1, 3, 5), (9,)}

compare to lists and return the different indices and elements in python

I want to compare to lists and return the different indices and elements.
So I write the following code:
l1 = [1,1,1,1,1]
l2 = [1,2,1,1,3]
ind = []
diff = []
for i in range(len(l1)):
if l1[i] != l2[i]:
ind.append(i)
diff.append([l1[i], l2[i]])
print ind
print diff
# output:
# [1, 4]
# [[1, 2], [1, 3]]
The code works, but are there any better ways to do that?
Update the Question:
I want to ask for another solutions, for example with the iterator, or ternary expression like [a,b](expression) (Not the easiest way like what I did. I want to exclude it.) Thanks very much for the patient! :)
You could use a list comprehension to output all the information in a single list.
>>> [[idx, (i,j)] for idx, (i,j) in enumerate(zip(l1, l2)) if i != j]
[[1, (1, 2)], [4, (1, 3)]]
This will produce a list where each element is: [index, (first value, second value)] so all the information regarding a single difference is together.
An alternative way is the following
>>> l1 = [1,1,1,1,1]
>>> l2 = [1,2,1,1,3]
>>> z = zip(l1,l2)
>>> ind = [i for i, x in enumerate(z) if x[0] != x[1]]
>>> ind
[1, 4]
>>> diff = [z[i] for i in ind]
>>> diff
[(1, 2), (1, 3)]
In Python3 you have to add a call to list around zip.
You can try functional style:
res = filter(lambda (idx, x): x[0] != x[1], enumerate(zip(l1, l2)))
# [(1, (1, 2)), (4, (1, 3))]
to unzip res you can use:
zip(*res)
# [(1, 4), ((1, 2), (1, 3))]

how to find the max number of items in a list such that certain pairs are not together in the output?

I have a list of numbers
l = [1,2,3,4,5]
and a list of tuples which describe which items should not be in the output together.
gl_distribute = [(1, 2), (1,4), (1, 5), (2, 3), (3, 4)]
the possible lists are
[1,3]
[2,4,5]
[3,5]
and I want my algorithm to give me the second one [2,4,5]
I was thinking to do it recursively.
In the first case (t1) I call my recursive algorithm with all the items except the 1st, and in the second case (t2) I call it again removing the pairs from gl_distribute where the 1st item appears.
Here is my algorithm
def check_distribute(items, distribute):
i = sorted(items[:])
d = distribute[:]
if not i:
return []
if not d:
return i
if len(remove_from_distribute(i, d)) == len(d):
return i
first = i[0]
rest = items[1:]
distr_without_first = remove_from_distribute([first], d)
t1 = check_distribute(rest, d)
t2 = check_distribute(rest, distr_without_first)
t2.append(first)
if len(t1) >= len(t2):
return t1
else:
return t2
The remove_from_distribute(items, distr_list) removes the pairs from distr_list that include any of the items in items.
def remove_from_distribute(items, distribute_list):
new_distr = distribute_list[:]
for item in items:
for pair in distribute_list:
x, y = pair
if x == item or y == item and pair in new_distr:
new_distr.remove((x,y))
if new_distr:
return new_distr
else:
return []
My output is [4, 5, 3, 2, 1] which obviously is not correct. Can you tell me what I am doing wrong here? Or can you give me a better way to approach this?
I will suggest an alternative approach.
Assuming your list and your distribution are sorted and your list is length of n, and your distribution is length of m.
First, create a list of two tuples with all valid combinations. This should be a O(n^2) solution.
Once you have the list, it's just a simple loop through the valid combination and find the longest list. There are probably some better solutions to further reduce the complexity.
Here are my sample codes:
def get_valid():
seq = [1, 2, 3, 4, 5]
gl_dist = [(1, 2), (1,4), (1, 5), (2, 3), (3, 4)]
gl_index = 0
valid = []
for i in xrange(len(seq)):
for j in xrange(i+1, len(seq)):
if gl_index < len(gl_dist):
if (seq[i], seq[j]) != gl_dist[gl_index] :
valid.append((seq[i], seq[j]))
else:
gl_index += 1
else:
valid.append((seq[i], seq[j]))
return valid
>>>> get_valid()
[(1, 3), (2, 4), (2, 5), (3, 5), (4, 5)]
def get_list():
total = get_valid()
start = total[0][0]
result = [start]
for i, j in total:
if i == start:
result.append(j)
else:
start = i
return_result = list(result)
result = [i, j]
yield return_result
yield list(result)
raise StopIteration
>>> list(get_list())
[[1, 3], [2, 4, 5], [3, 5], [4, 5]]
I am not sure I fully understand your output as I think 4,5 and 5,2 should be possible lists as they are not in the list of tuples:
If so you could use itertools to get the combinations and filter based on the gl_distribute list using sets to see if any two numbers in the different combinations in combs contains two elements that should not be together, then get the max
combs = (combinations(l,r) for r in range(2,len(l)))
final = []
for x in combs:
final += x
res = max(filter(lambda x: not any(len(set(x).intersection(s)) == 2 for s in gl_distribute),final),key=len)
print res
(2, 4, 5)

Getting the different between two 2D lists

I have a 2D list of lists, I am doing some stuff to it and getting, as a result a slightly modified 2d lists of lists. I cannot track what changes are being made until after I get the new list back. I want to get a list of all the items that have been changed such that
[[1,2,3], [4,5,6], [7,8,9]] becomes [[1,None,3], [4,None,6], [7,None, None]] and I would get a list [(0,1), (1,1), (2, 1), (2,2)] I know you can normally do list(set(a)-set(b)) but when I tried it I got TypeError: unhashable type: 'list' So what is the most efficient way of doing this?
Using zip, enumerate and a generator function:
def diff(lis1, lis2):
for i, (x, y) in enumerate(zip(lis1, lis2)):
for j, (x1, y1) in enumerate(zip(x, y)):
if x1 != y1:
yield i, j
...
>>> lis1 = [[1,2,3], [4,5,6], [7,8,9]]
>>> lis2 = [[1,None,3], [4,None,6], [7,None, None]]
>>> list(diff(lis1, lis2))
[(0, 1), (1, 1), (2, 1), (2, 2)]
Using list comprehension:
>>> a = [[1,2,3], [4,5,6], [7,8,9]]
>>> b = [[1,None,3], [4,None,6], [7,None, None]]
>>> [(i,j) for i, row in enumerate(a) for j, x in enumerate(row) if b[i][j] != x]
[(0, 1), (1, 1), (2, 1), (2, 2)]
If the lists have a regular structure, that is each of the sub-lists has the same length, and you don't mind using external packages, numpy can help.
import numpy as np
a = np.array([[1,2,3], [4,5,6], [7,8,9]])
b = np.array([[1,None,3], [4,None,6], [7,None, None]])
print(np.where(a!=b))
>>>(array([0, 1, 2, 2]), array([1, 1, 1, 2]))

Categories

Resources