问题
What is the most efficient way in python for picking multiple n consecutive integers from n consecutive list, picking up one integer from each list. Here n is quite large..say in the order of 100s.
L1 = [5,3,2,7,1]
L2 = [3,5,6,8,9,21,2]
L3 = [5,3,6,7,3,9]
I'd like to print out the ranges of consecutive integers from consecutive lists, where first element is picked up from first list, second element from second list and so on and so forth:
Candidate solution [5,6,7], [1,2,3], [7,8,9]
回答1:
L1 = [5,3,2,7,1]
L2 = [3,5,6,8,9,21,2]
L3 = [5,3,6,7,3,9]
cons_l = []
L = [L2] + [L3] #+[L4] #+ ...+ ..... ### Add any number of list here..
j = 0
for l1 in L1:
cons_l.append([])
cons_l[j].append(l1)
for l in range(0, len(L)):
if l1+l+1 in L[l]:
cons_l[j].append(l1+l+1)
else:
del cons_l[j]
j -= 1
break
j += 1
print cons_l
回答2:
I'd try sorting the lists first, using an efficient sorting algorithm. You can try Bubble Sort but other sorting algorithms might work as well.
You can then run through the integer from 1-n and look for continuous ranges of integer in the string. This way you have a maximum of n² operations for the sorting and n operations for the "finding".
Is this fast enough for you?
回答3:
You can use list comprehensions:
In [23]: ls = [[5,3,2,7,1],[3,5,6,8,9,21,2],[5,3,6,7,3,9],]
In [24]: l = len(ls)
In [25]: [list(range(s,s+l)) for s in ls[0] if all(i in l for i,l in zip(range(s+1,s+l),ls[1:]))]
Out[25]: [[5, 6, 7], [7, 8, 9], [1, 2, 3]]
The gust of it is, for every number in the first list generate a sequence of incremented numbers and check if each one is contained in the corresponding list in the sequence of remaining lists.
Note that all
stops iterating over the generator expression as soon as a condition is not satisfied, improving the efficiency of the method.
For a LARGE instance of the problem, it may be worth to convert all the lists to sets before the list comprehension, ls = [set(l) for l in ls]
Addendum
A variation w/o list comprehension using a for
loop and a conditional statement, note that the inner lists were converted to sets before the search for sequences.
ls = [[5, 3, 2, 7, 1], [3, 5, 6, 8, 9, 21, 2], [5, 3, 6, 7, 3, 9]]
l = len(ls)
ls = [set(li) for li in ls]
candidates = []
for n in ls[0]:
if all(i in l for i, l in zip(range(n+1, n+l), ls[1:])):
candidates.append(list(range(n, n+l)))
回答4:
Maybe using sets will be fast enough for your application? Is a bit brute force-y, but if I understood correctly, it is compliant with your restrictions:
lists = [
[5,3,2,7,1],
[3,5,6,8,9,21,2],
[5,3,6,7,3,9],
]
candidates = list()
# Without the first one
rest_of_sets = [set(l) for l in lists[1:]]
for fe in lists[0]:
skip_partial = False
for i, s in enumerate(rest_of_sets, 1):
if fe + i not in s:
skip_partial = True
break
if not skip_partial:
candidates.append(range(fe, fe+len(sets)))
print candidates
来源:https://stackoverflow.com/questions/36976419/identify-groups-of-continuous-numbers-from-consecutive-list-in-python