Reputation: 855
I have a variable which looks like this: my_value = 188
and I have a list which looks like this:
my_list = [
['Morocco', 'Meat', '190,00', '0,15'],
['Morocco', 'Meat', '189,90', '0,32'],
['Morocco', 'Meat', '189,38', '0,44'],
['Morocco', 'Meat', '188,94', '0,60'],
['Morocco', 'Meat', '188,49', '0,78'],
['Morocco', 'Meat', '187,99', '0,101'],
['Spain', 'Meat', '190,76', '0,10'],
['Spain', 'Meat', '190,16', '0,20'],
['Spain', 'Meat', '189,56', '0,35'],
['Spain', 'Meat', '189,01', '0,40'],
['Spain', 'Meat', '188,13', '0,75'],
['Spain', 'Meat', '187,95', '0,85'],
['Italy', 'Meat', '190,20', '0,11'],
['Italy', 'Meat', '190,10', '0,31'],
['Italy', 'Meat', '189,32', '0,45'],
['Italy', 'Meat', '188,61', '0,67'],
['Italy', 'Meat', '188,01', '0,72'],
['Italy', 'Meat', '187,36', '0,80']]
As you can see in my_list
the numbers in index [2]
are descending while the numbers in index [3]
are ascending. Now for every list I want to check at what index [3]
is index [2]
the closest to my_value
BUT it should not fall below my_value.
I tried below code:
for key,sublists in itertools.groupby(my_list,lambda y:y[0]):
v=[] #initialize it in case no element fulfill the condition
for v in itertools.takewhile(lambda x:float(x[-1].replace(",","."))<my_value ,sublists):
pass
if v:
print(v[-1])
I received the following output:
0,101
0,85
0,80
The output I want is:
0,78
0,75
0,72
Upvotes: 1
Views: 196
Reputation: 1996
my_value = 188
numbers = [float(line[2].replace(',', '.')) for line in my_list]
minima = [(num - my_value, line[3]) for num, line in zip(numbers, my_list) if num >= my_value]
minima = sorted(minima, key=lambda x: x[0])
top3 = [val[1] for val in minima[:3]]
print(top3)
First I create a list numbers
which holds the values of index 2 of each list in my_list
converted to a float, so we are actually able to perform calculations on these numbers. This is done using a list comprehension.
Then I create a new list minima
where I calculate the difference between my_value
and all values in numbers
, with the condition that the value in numbers has to be greater than or equal to my_number
. By using zip(number, my_list)
I simultaneously loop of both the list numbers
and my_list
so that I can put together the differense num - myvalue
together with the respective value in index 3 of my_list
into a tuple.
The list minima
then looks like this:
[(2.0, '0,15'),
(1.9000000000000057, '0,32'),
(1.3799999999999955, '0,44'),
(0.9399999999999977, '0,60'),
(0.4900000000000091, '0,78'),
(2.759999999999991, '0,10'),
(2.1599999999999966, '0,20'),
(1.5600000000000023, '0,35'),
(1.009999999999991, '0,40'),
(0.12999999999999545, '0,75'),
(2.1999999999999886, '0,11'),
(2.0999999999999943, '0,31'),
(1.3199999999999932, '0,45'),
(0.6100000000000136, '0,67'),
(0.009999999999990905, '0,72')]
Then I sort that list in ascending order by its first value in the tuple which is the difference between my_value
and the numbers in index 3. I then take the first three and return just the second value in the tuple.
Just on a sidenote: If you are dealing with tabular data like this, it might be a good idea to look into the pandas library. Another answer on this post shows a way to do this with pandas. It can often be easier and more user friendly to deal with tabular data with that library because it offers alot of functionality to easily perform alot of data manipulation and analysis.
Upvotes: 2
Reputation: 6029
This is the kind of work where pandas
comes to the rescue:
import pandas as pd
my_value = 188
my_list = [] # complete this with your list above
df = pd.DataFrame(my_list) # make a DataFrame out of your list
df[2] = df[2].str.replace(",", ".").astype(float) # convert those strings to actual floats
df[3] = df[3].str.replace(",", ".").astype(float)
selected = df[df[2]>my_value].groupby(by=0).agg({2:'min',3:'last'}) # selects what you want
print(list(selected[3])) # if you just want those values
will output
[0.72, 0.78, 0.75]
selected
will look like:
0 2 3
Italy 188.01 0.72
Morocco 188.49 0.78
Spain 188.13 0.75
Upvotes: 2
Reputation: 66
Why not use the built-in sort()?:
my_list = [row for row in my_list if float(row[2].replace(',','.')) >= my_value]
my_list.sort(key=lambda l:float(l[2].replace(',','.')))
for row in my_list:
print(row)
>
['Italy', 'Meat', '188,01', '0,72']
['Spain', 'Meat', '188,13', '0,75']
['Morocco', 'Meat', '188,49', '0,78']
['Italy', 'Meat', '188,61', '0,67']
['Morocco', 'Meat', '188,94', '0,60']
['Spain', 'Meat', '189,01', '0,40']
['Italy', 'Meat', '189,32', '0,45']
['Morocco', 'Meat', '189,38', '0,44']
['Spain', 'Meat', '189,56', '0,35']
['Morocco', 'Meat', '189,90', '0,32']
['Morocco', 'Meat', '190,00', '0,15']
['Italy', 'Meat', '190,10', '0,31']
['Spain', 'Meat', '190,16', '0,20']
['Italy', 'Meat', '190,20', '0,11']
['Spain', 'Meat', '190,76', '0,10']
Upvotes: -1