jblew
jblew

Reputation: 294

Find "x" greatest differences in Python list

Let's say I have a list of data... say stock prices for example, and I want to find out more about the differences between each element of the list - particularly the greatest differnece. In this case, it would be finding the 2 prices that exhibit the greatest change (i.e. greatest gain or loss).

Now, I don't simply want to find the singular greatest difference. I want to find maybe the 5 greatest differences - where all 5 pairs of numbers used to calculate the difference are unique and don't converge upon the same solution.

One way this could be done is with nested for loops like so:

nums = [1,2,3,4,5]

for i in nums:
    for x in nums:
        return x-i

But I feel this method is really clunky and doesn't solve the question at hand. Is there a better way to do this? Thanks!

Edit:

Solution for those interested

I used a modified version of @Chris_Rands answer to solve the problem. Basically, this function just finds the single greatest difference and then removes each element from the original list and does this process until only 1 element is left (when you can't find another diff). The result is an array of tuples containing 100% unique pairs of the greatest differences from the dataset:

from itertools import combinations
from heapq import nlargest

nums = [98,34,513,352,3523,308,13]

def findTrades(list_, amount):
    Trades_ = []

    while len(list_) >= 2:
        res = nlargest(1, combinations(list_, 2), key = lambda x: abs(x[0]-x[1]))
        Trades_.append(res)
        for i in res[0]:
            list_ = [x for x in list_ if x != i]

    return sorted(Trades_)[-amount:]

print (findTrades(nums, 3))

Upvotes: 1

Views: 581

Answers (7)

dawg
dawg

Reputation: 103814

Take the cartisean product and use max:

from itertools import combinations 
nums = [1,2,3,4,5]
max(combinations(nums,2), key=lambda t: abs(t[0]-t[1]))
# (1,5)

If you want them sorted by difference:

sorted(combinations(nums,2), key=lambda t: abs(t[0]-t[1]), reverse=True)
[(1, 5), (1, 4), (2, 5), (1, 3), (2, 4), (3, 5), (1, 2), (2, 3), (3, 4), (4, 5)]

Upvotes: 2

HakunaMaData
HakunaMaData

Reputation: 1321

You could try using Matrices:

l = np.array([1,2,3,4])
a = np.tile(l,(len(l),1))
a - a.T

enter image description here

This will give you the difference between every two pairs of elements. Now you can pick the largest n pairs.

b.ravel()[np.argsort(b.ravel())][-4:] will give you the largest 4 values

array([1, 2, 2, 3])

Upvotes: 0

Mahin Kannan
Mahin Kannan

Reputation: 101

sol holds all the five greatest differences. I replace the minimum difference every time while iterating. Should be simple to understand. (I have not checked for edge cases and other problems)

lis=[1,2,6,3,76,44,98,23,56,87,23,65,19,73]
sol=[0,0,0,0,0]
for i in range(len(lis)):
  for j in range(len(lis)):
    if abs(lis[i]-lis[j])>min(sol):
      sol[sol.index(min(sol))]=lis[i]-lis[j]

print(sol)

#returned this [86, 97, 92, 96, 95]

Upvotes: 0

GeeTransit
GeeTransit

Reputation: 1468

Here's a function that takes a list / tuple and returns the 5 greatest differenced. Note this doesn't use any other dependencies other than the builtins.

Usage:
differences(list_, length)
list_ is the input list that you want to check.
length is the number of differences you want to record.

def differences(list_, length):
    diffs = list(0 for _ in range(length))
    for i, j in enumerate(list_):
        for k in list_[i + 1:]:
            if max(j, k) - min(j, k) > min(diffs):
                diffs[0] = max(j, k) - min(j, k)
                diffs = sorted(diffs)
    return diffs

The greatest 5 will be what is returned. If there's only 3 items in a list which makes 3 differences, the last two will be 0 as you cannot get a negative difference with this code.

Upvotes: 1

Chris_Rands
Chris_Rands

Reputation: 41168

Here x=3. Using heapq.nlargest is better than sorting for small values of x.

>>> from itertools import combinations
>>> from heapq import nlargest
>>> nlargest(3, combinations(nums, 2), key = lambda x: abs(x[0]-x[1]))
[(1, 5), (1, 4), (2, 5)]

Upvotes: 3

gold_cy
gold_cy

Reputation: 14216

If I understand correctly:

from operator import sub
from itertools import combinations

gen = sorted(set(abs(sub(*tup)) for tup in combinations(nums, 2)), reverse=True)

gen

[4, 3, 2, 1]

Upvotes: 1

spencer.pinegar
spencer.pinegar

Reputation: 460

I would iterate through the list once and find the 3 largest numbers in the list and the 3 smallest numbers in the list. Find the differences between all of these numbers and take the 3 largest. This will be performant and ensure the you found the top 5 largest differences.

Upvotes: 0

Related Questions