0

I have 2 lists:

my_values = ['0,78', '0,40', '0,67']

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,78'],
    ['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'],
]

I have a code which is checking the following:

  1. For Morocco it checks at what index[2] inmy_listisindex[3]in my_values == 0,78
  2. For Spain it checks at what index[2] inmy_list isindex[3]in my_values == 0,40
  3. For Italy it checks at what index[2] in my_list isindex[3]in my_values == 0,67

Now I have a problem, as you can see 0,78 in my_values is present in Morocco AND Spain, I only want it to check it for Morocco.

This is my code:

yet_another_list = [i[2] for i in my_list if i[3] in my_values]
print(yet_another_list)

This is my output:

['188,49', '189,01', '187,95', '188,61']

This is my prefered output:

['188,49', '189,01', '188,61']

As you can see I want index[1] of my_values to be only used for Morocco, and index[2] for Spain etc... Please note that in my officla dataset my_lists contains a lot more countries...

#ADDED. I even tried Pandas but still received the same output.

df=pd.DataFrame(my_list)
df['Filter']=np.where([i in my_values for i in df[3]],"Yes","")
my_out_list=list(df[2][df['Filter']=='Yes'])

print(my_out_list)

>> 
['188,49', '189,01', '187,95', '188,61']
TangerCity
  • 775
  • 2
  • 7
  • 13
  • You are misusing a value as unique identifier that is not a unique identifier. – C14L Jan 04 '21 at 10:16
  • When someone leaves a comment instead of an answer, it usually means they do not have a complete solution. Maybe review the [help] to better understand how this site works. – tripleee Jan 04 '21 at 10:20
  • Switching to Pandas but copying the same bug obviously doesn't solve the problem, though it will probably scale handsomely. – tripleee Jan 04 '21 at 10:27

3 Answers3

1

I'd recommend using a dictionary and then filtering your dataset

my_values = {'Morocco': '0,78', 'Spain': '0,40', 'Italy': '0,67'}

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,78'],
    ['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'],
]


print([e[2] for e in filter(lambda x: x[3] == my_values[x[0]], my_list)])

>>> ['188,49', '189,01', '188,61']

As a side note, if you're working with much larger data sets it might be beneficial to look at the pandas package, a popular Python library for data analysis

ScootCork
  • 3,411
  • 12
  • 22
  • I understand your answer but it doesnt solve my much bigger dataset. Do you know how to solve this with Pandas? – TangerCity Jan 04 '21 at 10:17
  • Why do you think this doesn't work for a bigger data set? – tripleee Jan 04 '21 at 10:25
  • @tripleee because I manually need to fix `my_values`. – TangerCity Jan 04 '21 at 10:31
  • That doesn't make this a bad answer. Your current data structure is cumbersome and will probably introduce additional problems down the line. – tripleee Jan 04 '21 at 10:32
  • Ok, then using pandas won't really solve that problem. If the order of cities in `my_list` matches the order of the values in `my_values` then you could make use of that with some extra processing. – ScootCork Jan 04 '21 at 10:36
1

Using original data structures with iterators.

def get_values(my_list_, *my_values_):
    ''' Finds the desired result using my_list_ and my_values
        my_valuesis one or more list
    '''
    output = []
    # Find values for each list in my_values_
    for my_values__ in my_values_:
         # Create iterators 
        result = []
        my_values_iter = iter(my_values__) # iterator for current list of values
        my_list_iter = iter(my_list_)  # from beginning of my_list_

        v = next(my_values_iter, None)
        i = next(my_list_iter, None)
        while v and i:
            if v == i[3]:
                # found match
                result.append(i[2])
                v = next(my_values_iter, None) # Next value to find in my_values
                i = next(my_list_iter, None)   # Next value to check in my_list
            else:
                # try next value from my_list
                i = next(my_list_iter, None)   # Next value to check in my_list
        output.append(result)
        
     if len(output) == 1:
        return output[0]  # Only single list
    else:
        return tuple(x for x in output) # Output tuple of lists
    

Usage

# Single list of values
a = get_values(my_list, ['0,78', '0,40', '0,67'])
print(f'a = {a}') # Output: a = ['188,49', '189,01', '188,61']

# Two list of values (can handle an arbitrary number)
a, b = get_values(my_list, ['0,78', '0,40', '0,67'], ['0,78', '0,10', '0,78'])
print(f'a = {a}, b = {b}') # Output: a = ['188,49', '189,01', '188,61'], b = ['188,49', '190,76', '187,95']
DarrylG
  • 16,732
  • 2
  • 17
  • 23
  • @DarryIG, this seems a good one. Cant it be any shorter though? I have another addition though. What if I had another extra list named `my_values_2` with also 3 values inside of it. I can copy paste the code, but I prefer doing it all in once... – TangerCity Jan 04 '21 at 11:04
  • @TanGerCity--meaning you want the resultant list from my_values_1 and my_values_2. Does my_values_2 start check my_list from the beginning or does it continue from where my_values_1 left off in my_list? – DarrylG Jan 04 '21 at 11:09
  • @DarryIG, it starts from the beginning again. It actually is the same thing again just different values inside `my_values_2` – TangerCity Jan 04 '21 at 11:11
  • @TangerCity--updated to handle 1 or more list of values. – DarrylG Jan 04 '21 at 11:25
  • @DarryIG but that means I should have 2 output lists as well..... – TangerCity Jan 04 '21 at 11:28
  • @TangerCity--current solution placed all values in one list. Are you saying you want an output list for each set of values? Actually, a 2D list? – DarrylG Jan 04 '21 at 11:30
  • can we do some private chat so I can explain you how I want it? – TangerCity Jan 04 '21 at 11:31
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/226816/discussion-between-darrylg-and-tangercity). – DarrylG Jan 04 '21 at 11:32
0

If I understand your requirement correctly, you want to loop over countries in the list, and simultaneously loop over the indices in the other list?

previous = my_list[0][0]
ind = 0
result = []
for item in my_list:
    if item[0] != previous:
        ind += 1
        previous = item[0]
    if item[3] == my_values[ind]:
        result.append(item[2])
print(result)

This will obviously throw an IndexError if you have more countries than values in my_values.

Perhaps a better approach would be to turn my_list into a dict where the keys are country names and the values are the values for that country, though.

tripleee
  • 175,061
  • 34
  • 275
  • 318