Python - Finding elements in a list efficiently
I have a list, list_a, that contains floating numbers:
list_a = [[[ 0 for i in range(40)] for j in range(1000)]for k in range(47)]
And I have a sorted version of this:
list_a_sorted = list_a
list_a_sorted[0].sort()
So list_a_sorted is sorted and contains values for list_a starting from the lowest first. Let's assume it is as follows:
[2.3,3.1.........9]
So 2.3 is the lowest value but how ca开发者_JS百科n I find out if this was the 8th element in list_a or the 15th or nth?
As my lists are quite large, I also need to do this as efficiently as possible? Any help would be appreciated, thanks
to find the position of an element in a list you can use l.index(something)
http://docs.python.org/library/stdtypes.html#typesseq
if you want to find the n
smallest values in an unsorted list look at heapq.nsmallest()
which may be more efficient if n
isn't too large. To find the position of the smallest values try this:
>>> from heapq import nsmallest
>>> from random import random
>>> values = [random() for i in range(20)]
>>> values
[0.012227103410989537, 0.9782624648209769, 0.9896111545377924, 0.9033620518745159, 0.6767780103989406, 0.4595455061820246, 0.39814471642551696, 0.6904798136040561, 0.8727083752258934, 0.6680153337266017, 0.606044647078923, 0.5644656135679249, 0.934351848916147, 0.05955628567745763, 0.7236000566917332, 0.8303865367817055, 0.9671576336593124, 0.3164892315873573, 0.8416372881413415, 0.5009057933309073]
>>> nsmallest(4, range(len(values)), key=lambda i: values[i])
[0, 13, 17, 6]
Or faster but slightly less clear:
>>> nsmallest(4, range(len(values)), key=values.__getitem__)
[0, 13, 17, 6]
For your list you may want something like (untested code):
def indices():
for k in range(47):
for j in range(1000):
for i in range(40):
yield k, j, i
def keyfn(ind):
k, j, i = ind
return list_a[k][j][i]
print(nsmallest(4, indices(), key=keyfn))
If speed is of essence (and you have something like "create once, lookup often" and if you don't have any duplicate entries (if you do use set
) then I'd suggest that you create an dictionary upon creation of the list with each item as key and it's index as value. In this case you'll always have O(1) lookuptime regardless of the length of the dictionary. Many ifs there...
Answering the question in the comments...
If L
is the list of numbers, this will return the indicies of the n
smallest items
[j for i,j in sorted((j,i) for i,j in enumerate(L))[:n]]
Here is another way that is a little more tricky
sorted(range(len(L)), key=L.__getitem__)[:n]
Which is more efficient is left as an exercise for the reader :)
精彩评论