Darshan Chaudhary
Darshan Chaudhary

Reputation: 2233

Python : list comprehension + filter

I have a string from which I wish to extract vowels and consonants along with their indices.

I am thinking about :

a = "HELLO"
list_ = list(a)
vow = [(x, i) for i,x in enumerate(list_) if x in ['A', 'E', 'I', 'O', 'U']]
cons = [(x, i) for i, x in enumerate(list_) if x not in j for j in list_ if j in ['A', 'E', 'I', 'O', 'U']]

However, I am getting NameError (saying j is not defined). Why am I not able to nest my list comprehension.

My desired output :

vows : [('E', 1), ('O', 4)]
cons : [('H', 0), ('L', 2), ('L', 3)]

Upvotes: 2

Views: 1025

Answers (5)

Open AI - Opting Out
Open AI - Opting Out

Reputation: 24133

You can check for membership in a string:

>>> 'I' in 'AEIOU'
True

You could convert each character in a string to a member of a set, for slightly faster searching:

>>> 'Z' in set('AEIOU')
False

You don't need the second inner loop:

>>> vowels = set('AEIOU')
>>> vows = [(char, index) for index, char in enumerate(word) if char in vowels]
>>> cons = [(char, index) for index, char in enumerate(word) if char not in vowels]

Upvotes: 2

Serge Ballesta
Serge Ballesta

Reputation: 148880

The correct syntax would be to explicitely make the inner loop a list comprehension:

cons = [(x, i) for i, x in enumerate(list_) if x not in [ j for
            j in list_ if j in ['A', 'E', 'I', 'O', 'U']]]

But here the correct way to get consonants would be simply (as already said by others):

cons = [(x, i) for i,x in enumerate(list_) if x not in ['A', 'E', 'I', 'O', 'U']]

Upvotes: 2

Anand S Kumar
Anand S Kumar

Reputation: 90879

The issue with your second list comprehension is that ideally the if condition should go at the end (after the second for loop , only then j would we accessible). But you really do not need that, simply check if x is not in the list of vowels. Example -

cons = [(x, i) for i,x in enumerate(list_) if x not in ['A', 'E', 'I', 'O', 'U']]

Demo -

>>> a = "HELLO"
>>> list_ = list(a)
>>> vow = [(x, i) for i,x in enumerate(list_) if x in ['A', 'E', 'I', 'O', 'U']]
>>> cons = [(x, i) for i,x in enumerate(list_) if x not in ['A', 'E', 'I', 'O', 'U']]
>>> vow
[('E', 1), ('O', 4)]
>>> cons
[('H', 0), ('L', 2), ('L', 3)]

You can make this a bit faster by using set for vowels and you do not really need list_ , you can enumerate over a itself, and get exactly same result. Example -

vowel_set = {'A', 'E', 'I', 'O', 'U'}
vow = [(x, i) for i,x in enumerate(a) if x in vowel_set]
cons = [(x, i) for i,x in enumerate(a) if x not in vowel_set]

Demo -

>>> a = "HELLO"
>>> vowel_set = {'A', 'E', 'I', 'O', 'U'}
>>> vow = [(x, i) for i,x in enumerate(a) if x in vowel_set]
>>> cons = [(x, i) for i,x in enumerate(a) if x not in vowel_set]
>>> vow
[('E', 1), ('O', 4)]
>>> cons
[('H', 0), ('L', 2), ('L', 3)]

Upvotes: 4

Hayley Guillou
Hayley Guillou

Reputation: 3973

You're over-complicating it

a = "HELLO"
list_ = list(a)
vow = [(x, i) for i,x in enumerate(list_) if x in ['A', 'E', 'I', 'O', 'U']]
cons = [(x, i) for i, x in enumerate(list_) if x not in ['A', 'E', 'I', 'O', 'U']]

See Anand S Kumar's answer for details :)


The mistake in your nesting is that you need to nest it again

cons = [(x, i) for i, x in enumerate(list_) if x not in [j for j in list_ if j in ['A', 'E', 'I', 'O', 'U']]]

Upvotes: 2

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798526

Rule #1 about nested LCs in Python: The outer loop goes first.

cons = [(x, i) for j in list_ if j in ['A', 'E', 'I', 'O', 'U'] for i, x in enumerate(list_) if x not in j]

But this will give the wrong result since you should just be using not in in the first place instead.

Upvotes: 2

Related Questions