Reputation: 425
I am better off explaining with an example
Suppose, I have a list [6,3,5,1,4,2].
Starting from index 0, find all items that are smaller (that have not been marked) than the value at that index.
Index 0: [6,3,5,1,4,2]
Elements less than 6: 5{3,5,1,4,2}
Visited array: [1 0 0 0 0 0]
Index 1: [6,3,5,1,4,2]
Elements less than 3: 2 {1,2}
Visited array: [1 1 0 0 0 0]
Index 2: [6,3,5,1,4,2]
Elements less than 5: 3 {1,4,2}
Visited array: [1 1 1 0 0 0]
Index 3: [6,3,5,1,4,2]
Elements less than 1: 0 {NULL}
Visited array: [1 1 1 1 0 0]
Index 4: [6,3,5,1,4,2]
Elements less than 4: 1 {2}
Visited array: [1 1 1 1 1 0]
This yields an array as [5 2 3 0 1 0]
Currently using,
def get_diff(lis):
ans=[]
for index,elem in enumerate(lis):
number_of_smaller=len(filter(lambda x:x<elem ,lis[index+1:]))
ans.append(number_of_smaller)
return ans
However, I have a feeling that this will not be efficient. How do I make it worthy of a huge list? Do I smell prefix sums?. Thanks,
Upvotes: 2
Views: 462
Reputation: 107347
You can simply use a list comprehension within a dict comprehension to preserve the item as the key and the items which are less than it as the value (and use collections.OrderedDict
to preserve the order):
>>> from collections import OrderedDict
>>> def get_diff(lis):
... return OrderedDict((item,[i for i in lis if i<item]) for item in lis)
Since your condition is <
there is no need to exclude the item itself, because that the cost of removing it in comparison is greater than including it.
Also if you want to preserve the indices to you can use enumerate
to loop over your list :
def get_diff(lis):
return OrderedDict((item,index),[i for i in lis if i<item]) for index,item in enumerate(lis))
And if you want to count the number of that items you can use a generator expression within sum
function :
>>> from collections import OrderedDict
>>> def get_diff(lis):
... return OrderedDict((item,sum(1 for i in lis if i<item)) for item in lis)
NOTE: if you want to count the item less than any item after that (with larger index) you can simply use a indexing in your loop :
>>> def get_diff(lis):
... return OrderedDict((item,sum(1 for i in lis[index:] if i<item)) for index,item in enumerate(lis))
...
>>> get_diff(l).values()
[5, 2, 3, 0, 1, 0]
Upvotes: 2
Reputation: 955
my_list = [6,3,5,1,4,2]
def get_diff(lis):
result = []
for visited, i in enumerate(range(len(lis))):
limit = lis[i]
elem = filter(None, [x if x < limit else None for x in lis][visited + 1:])
result.append(len(elem))
return result
print get_diff(my_list)
#[5, 2, 3, 0, 1, 0]
Upvotes: -1