Reputation: 490
This one is causing me a headache, and I am having trouble to find a solution with a for-loop.
Basically, my data looks like this:
short_list = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12] ]
long_list = [ [1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [6, 7, 8, 9, 10], [9, 10, 11, 12, 13] ]
I would need to know how many times each number from each row in the short_list appears in each row of the long_list, and the comparison is NOT needed when both list indices are the same, because they come from the same data set.
Example: I need to know the occurrence of each number in [1, 2, 3] in the long_list rows [2, 3, 4, 5, 6], [6, 7, 8, 9, 10] and [9, 10, 11, 12, 13]. And then continue with the next data row in short_list, etc.
Upvotes: 5
Views: 93
Reputation: 26315
Possible Approach:
short_list
.long_list
that is not the same index as the current list, and convert it to a set. collections.Counter()
to store the counts for each element in short list that appears in the flattened list. Demo:
from collections import Counter
from itertools import chain
short_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
long_list = [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [6, 7, 8, 9, 10], [9, 10, 11, 12, 13]]
for i, short_lst in enumerate(short_list):
to_check = set(chain.from_iterable(long_list[:i] + long_list[i+1:]))
print(Counter(x for x in short_lst if x in to_check))
Output:
Counter({2: 1, 3: 1})
Counter({4: 1, 5: 1, 6: 1})
Counter({9: 1})
Counter({10: 1})
Upvotes: 2
Reputation: 164623
This is a brute-force solution. I've amended the input data to make the results more interesting:
from collections import Counter
from toolz import concat
short_list = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12] ]
long_list = [ [1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [6, 7, 8, 9, 10], [2, 3, 11, 12, 13] ]
for idx, i in enumerate(short_list):
long_list_filtered = (x for x in concat(long_list[:idx] + long_list[idx+1:]) if x in set(i)))
print(idx, Counter(long_list_filtered))
# 0 Counter({2: 2, 3: 2})
# 1 Counter({4: 1, 5: 1, 6: 1})
# 2 Counter()
# 3 Counter({10: 1})
Upvotes: 2
Reputation: 1213
for L1 in short_list:
for L2 in long_list:
if not set(L1).issubset(set(L2)):
for x in L1:
print("{} has {} occurrences in {}".format(x, L2.count(x), L2))
Upvotes: 1
Reputation: 87064
Here's one way to do it. It's straight off the top of my head, so there is probably a much better way to do it.
from collections import defaultdict
short_list = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12] ]
long_list = [ [1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [6, 7, 8, 9, 10], [9, 10, 11, 12, 13] ]
occurrences = defaultdict(int)
for i, sl in enumerate(short_list):
for j, ll in enumerate(long_list):
if i != j:
for n in sl:
occurrences[n] += ll.count(n)
>>> occurrences
defaultdict(<class 'int'>, {1: 0, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 0, 8: 0, 9: 1, 10: 1, 11: 0, 12: 0})
Note that enumerate()
is used to provide indices while iterating. The indices are compared to ensure that sub-lists at the same relative position are not compared.
The result is a dictionary keyed by items from the short list with the values being the total count of that item in the long list sans the sublist with the same index.
Upvotes: 3
Reputation: 1701
short_list = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12] ]
long_list = [ [1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [6, 7, 8, 9, 10], [9, 10, 11, 12, 13] ]
occ = []
for si in short_list:
occi = []
for i, e in enumerate(si):
count = 0
for li in long_list:
for j, e1 in enumerate(li):
if i == j:
continue
elif e == e1:
count += 1
occi.append(count)
occ.append(occi)
print occ
This should work, Happy coding :)
Upvotes: 0