Reputation: 59
I have three lists. Two lists of string, and one list of float. I used zip to match one list of string and float together that are the same length to make a new string. Basically:
letters1 = ['a', 'b', 'c', 'd', 'e']
numbers = [0.0, 3.0, 5.0, 10.0, 28.0]
letters2 = ['a', 'c', 'e']
letnum = [i for i in zip(letters1, numbers)]
This gets me:
[('a', 0.0), ('b', 3.0), ('c', 5.0), ('d', 10.0), ('e', 28.0)]
I want to use the other list to get only [0.0, 5.0, 28.0]
, but I don't know how to return a list of float like that.
I tried using [x for x in letnum if x in letters2]
but that gave me []
.
I also know letnum = [i for _, i in zip(letters1, numbers)]
will get me [0.0, 3.0, 5.0, 10.0, 28.0]
but I don't know if that does anything.
Any help would be appreciated!
Upvotes: 3
Views: 69
Reputation: 57289
If you anticipate large lists, here's a linear solution using a lookup dictionary to enable grabbing a float for each element in letters2
in constant time instead of repeatedly iterating in a nested loop. Total time complexity is O(len(letters) + len(letters2))
which is optimal:
>>> letters1 = ['a', 'b', 'c', 'd', 'e']
>>> numbers = [0.0, 3.0, 5.0, 10.0, 28.0]
>>> letters2 = ['a', 'c', 'e']
>>> lookup = {x: y for x, y in zip(letters1, numbers)}
>>> [lookup[x] for x in letters2 if x in lookup]
[0.0, 5.0, 28.0]
The reason your original attempt doesn't work is [x for x in letnum if x in letters2]
tries to find a whole tuple x
in letters2
which only contains strings.
Upvotes: 1
Reputation: 61643
Let's consider the entire process at once (edited slightly because I misunderstood the requirement)
for
each of the letter
and number
pairs that we get by zip
ping together letters1
and numbers
, we want: the number
, but only if
the letter
was in letters2
.
So, we write it exactly like that, except that the element description goes at the front.
[number for letter, number in zip(letters1, numbers) if letter in letter2]
To cover your attempts:
I tried using
[x for x in letnum if x in letters2]
but that gave me[]
.
Yes, because x
is one of the pairs, and letters2
doesn't contain those pairs. You can fix this as in @vaichidrewar's answer by extracting the letter, x[0]
, for the comparison. Similarly, x
is one of the pairs, and you only want the number, so x[1]
extracts the number.
I also know letnum = [i for _, i in zip(letters1, numbers)] will get me [0.0, 3.0, 5.0, 10.0, 28.0] but I don't know if that does anything.
It's a start, in the sense that you are using unpacking for the zip
results to give separate names to the elements of each pair that you get. By convention, we use _
to refer to values that we don't care about; but you do care about both values (because you want the letter for the condition).
Upvotes: 1
Reputation: 22087
Would you try the following:
letters1 = ['a', 'b', 'c', 'd', 'e']
numbers = [0.0, 3.0, 5.0, 10.0, 28.0]
letters2 = ['a', 'c', 'e']
d = {}
for i in range(len(letters1)):
d[letters1[i]] = numbers[i]
letnum = [d[x] for x in letters2]
print(letnum)
Output:
[0.0, 5.0, 28.0]
Upvotes: 1
Reputation: 2162
convert zip object
into list
and access 0, 2, 5
index using range(0, len(numbers), 2)
letters1 = ['a', 'b', 'c', 'd', 'e']
numbers = [0.0, 3.0, 5.0, 10.0, 28.0]
letters2 = ['a', 'c', 'e']
letnum = [list(zip(letters1, numbers))[i] for i in range(0,len(numbers), 2)]
print(letnum)
Methiod-2
letnum = [i for i in zip(letters1, numbers) if i[0] in letters2]
Upvotes: 0
Reputation: 9621
Each element in letnum
is a tuple which is a pair of a letter and a float.
If you take the first element of the tuple and then check for existence in the letters2
list you will find a match.
[x for x in letnum if x[0] in letters2]
x[0]
is taking the first element of the tuple.
Upvotes: 3