In Python, how can I check if 2 numbers in a list are at a certain percentage of each other?


I have a large list of numbers, and I want to see if they are approximately equal. If 2 numbers are “approximately equal” (for my purposes), then both of them fall within 10% of each other (see the following 2 examples.) Then I want to sort them into separate lists of approximately equal numbers.

Example # 1 Compare 5.0 and 5.5: 5.5 +/- 10% = 4.95 to 6.05 (and 5.0 in this range) 5.0 +/- 10% = 4, 50 to 5.50 (and 5.5 in this range) Therefore, 5.0 and 5.5 are approximately equal.

Example # 2 Compare 5.0 and 5.6: 5.6 +/- 10% = 5.04 to 6.16 (and 5.0 in this range) 5.0 +/- 10% = 4.50 to 5.50 (and 5.6 in this range) Therefore, 5.0 and 5.6 are NOT approximately equal.

A summary of what I need to do: Input = {4.0, 4.1, 4.2, 4.0, 9.0, 9.4, 8.9, 4.3} Desired result = {4.0, 4.1, 4.2, 4.0, 4.3} and {9.0, 9.4, 8.9}

+4
source share
3 answers
input_list = [4.0, 4.1, 4.2, 4.0, 9.0, 9.4, 8.9, 4.3] results = {input_list[0]: [input_list[0]]} # Start with first value for value in input_list[1:]: # loop through our entire list after first value hi = value * 1.1 low = value * 0.9 print("Value: {0}\tHi: {1}\tLow:{2}".format(value, hi, low)) for existing in results: # search through our result set found_similar = False if low < existing < hi: # if we find a match results[existing].append(value) # we add our value to the list for that set found_similar = True break if not found_similar: # if we looped through our entire results without a match results[value] = [value] # Create a new entry in our results dictionary for entry in results: print(results[entry]) 

It gives:

 results = { 9.0: [9.0, 9.4, 8.9], 4.0: [4.0, 4.1, 4.2, 4.0, 4.3] } 

This code starts with the first value in your list and finds all subsequent values ​​that are within 10% of this. So, in your example, it starts with 4 and finds all similar values. Any value that does not exceed 10% is added to the new “set”.

So, as soon as it reaches 9.0, it sees that it does not match, so it adds a new result to the results dictionary with the key 9.0 . Now that he counts 9.4, he does not find a match in list 4.0, but finds a match in list 9.0. Therefore, he adds this value to the second result set.

+3
source

Here is a generator / set based method.

 def set_gen(nums): for seed in sorted(nums): yield tuple([n for n in nums if seed <= n and n/seed <= 1.1]) def remove_subsets(sets): for s in sets.copy(): [sets.remove(s2) for s2 in sets.difference([s]) if set(s2).issubset(s)] >>> nums = [4.0, 4.1, 4.2, 4.0, 9.0, 9.4, 8.9, 4.3] >>> x = set(num for num in set_gen(nums)) >>> remove_subsets(x) >>> list(x) [(9.0, 9.4, 8.9), (4.0, 4.1, 4.2, 4.0, 4.3)] >>> nums = [1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0] >>> x = set(num for num in set_gen(nums)) >>> remove_subsets(x) >>> list(x) [(1.9, 1.8), (1.5, 1.4), (1.4, 1.3), (1.2, 1.1), (1.7, 1.6), (1.5, 1.6), (1.3, 1.2), (1.9, 2.0), (1.0, 1.1), (1.8, 1.7)] 
0
source

You can do it:

 Input = {4.0, 4.1, 4.2, 4.0, 9.0, 9.4, 8.9, 4.3} wl=sorted(Input,reverse=True) apr=.1 out={} while wl: wn=wl.pop() out[wn]=[wn] while wl and wl[-1]<=wn*(1+apr): out[wn].append(wl.pop()) print [(k,out[k]) for k in sorted(out.keys())] 

Fingerprints:

 [(4.0, [4.0, 4.1, 4.2, 4.3]), (8.9, [8.9, 9.0, 9.4])] 

Try the example in the comments:

 >>> Input = {1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0} 

Print

 [(1.0, [1.0, 1.1]), (1.2, [1.2, 1.3]), (1.4, [1.4, 1.5]), (1.6, [1.6, 1.7]), (1.8, [1.8, 1.9]), (2.0, [2.0])] 
-1
source

Source: https://habr.com/ru/post/1479634/


All Articles