Python: 'as' keyword in list comprehension? - python

I know this won't work but you guys get the idea.
c = [m.split('=')[1] as a for m in matches if a != '1' ]
Is there a way to archive this? If you use a list comprehension like
c = [m.split('=')[1] as a for m in matches if m.split('=')[1] != '1' ]
two lists will be build from the split, right?

You can use use a generator expression inside the list comprehension:
c = [a for a in (m.split('=')[1] for m in matches) if a != '1']

It's sorta-possible, but when you find yourself resorting to awful hacks like the following, it's time to use a regular loop:
c = [a for m in matches for a in [m.split('=')[1]] if a != '1']

You can't do it, and there's no real point in using a nested map or nested list comprehension as the other solutions show. If you want to preprocess the list, just do:
whatIwant = (m.split('=')[1] for m in matches)
c = [a for a in whatIwant if a != 1]
Using a nested list comp or map saves nothing, since the entire list is still processed. All it does is reduce readability.

Something like this perhaps:
c = [ a for a, m in map(lambda x: (x.split('=')[1], x), matches) if a != '1' ]
you may want to use imap instead of map. Some cleaner version:
def right_eq(x): return (x.split('=')[1], x)
c = [ a for a, m in imap(right_eq, matches) if a != '1' ]

Related

Deleting list from a list of lists

I need to delete these lists inside of list that contains the / symbol.
List for example:
X = [['a/','$1'], ["c","d"]]
so X[0] should be deleted. The actual list are much longer and contains more instances of this condition.
I tried use something like:
print([l for l in X if l.count("/") <1])
But if I understand correctly because the / is attached to another symbol he is not counted.
Should I convert this list of lists to string, separate the / from another character, and then use the count function, or there is better solution?
One way to search "/" in each item in the sublists is to wrap a generator expression with any. Since you don't want sublists with "/" in it, the condition should be not any():
out = [lst for lst in X if not any('/' in x for x in lst)]
Output:
[['c', 'd']]
The call to filter() applies that lambda function to every list in X and filters out list with '/'.
result = list(filter(lambda l: not any('/' in s for s in l), X))
counter = 0
while counter < len(X):
removed = False
for i in X[counter]:
if '/' in i:
X.pop(counter)
removed = True
break
if not removed:
counter += 1
Given:
X = [['a/','$1'], ["c","d"]]
You can convert the sub lists to their repr string representations and detect the / in that string:
new_x=[sl for sl in X if not '/' in repr(sl)]
Or, you can use next:
new_x=[sl for sl in X if not next('/' in s for s in sl)]
Either:
>>> new_x
[['c', 'd']]

Filtering for tuples from another list and extracting values

I am working on handling two lists of tuples and deducing results.
For example:
A = [('Hi','NNG'),('Good','VV'),...n]
B = [('Happy','VA',1.0),('Hi','NNG',0.5)...n]
First, I'd like to match the words between A and B.
like 'Hi'='Happy' or 'Hi'='Hi'
Second, if they are same and match, then match word class.
whether 'NNG'='NNG' or 'NNG'='VV'
Third, if all these steps match, then extract the number!
like if A=[('Hi','NNG')] and B=('Hi','NNG',0.5)
Extract 0.5
Lastly, I want to multiply all numbers from extraction.
There are more than 1,000 tuples in each A, B. So 'for' loop will be necessary to find out this process.
How can I do this in Python?
Try something like this:
A = [('Hi', 'NNG'), ('Good', 'VV')]
B = [('Happy', 'VA', 1.0), ('Hi', 'NNG', 0.5)]
print(', '.join(repr(j[2]) for i in A for j in B if i[0] == j[0] and i[1] == j[1]))
# 0.5
One way is to use a set and (optionally) a dictionary. The benefit of this method is you also keep the key data to know where your values originated.
A = [('Hi','NNG'),('Good','VV')]
B = [('Happy','VA',1.0),('Hi','NNG',0.5)]
A_set = set(A)
res = {(i[0], i[1]): i[2] for i in B if (i[0], i[1]) in A_set}
res = list(res.values())
# [0.5]
To multiply all results in the list, see How can I multiply all items in a list together with Python?
Explanation
Use a dictionary comprehension with for i in B. What this does is return a tuple of results iterating through each element of B.
For example, when iterating the first element, you will find i[0] = 'Happy', i[1] = 'VA', i[2] = 1.0.
Since we loop through the whole list, we construct a dictionary of results with tuple keys from the first 2 elements.
Additionally, we add the criterion (i[0], i[1]) in A_set to filter as per required logic.
Python is so high level that it feels like English. So, the following working solution can be written very easily with minimum experience:
A = [('Hi','NNG'),('Good','VV')]
B = [('Happy','VA',1.0),('Hi','NNG',0.5)]
tot = 1
for ia in A:
for ib in B:
if ia == ib[:2]:
tot *= ib[2]
break # remove this line if multiple successful checks are possible
print(tot) # -> 0.5
zip() is your friend:
for tupA,tupB in zip(A,B):
if tupA[:2] == tupB[:2] : print(tupB[2])
To use fancy pythonic list comprehension:
results = [tubB[2] for tubA,tubB in zip(A,B) if tubA[:2] == tubB[:2] ]
But... why do I have a sneaky feeling this isn't what you want to do?

Matching characters in strings

I have 2 lists of strings:
list1 = ['GERMANY','FRANCE','SPAIN','PORTUAL','UK']
list2 = ['ERMANY','FRANCE','SPAN','PORTUGAL','K']
I wanted to obtain a list where only the respective strings with 1 character less are shown. i.e:
final_list = ['ERMANY','SPAN','K']
What's the best way to do it? Using regular expressions?
Thanks
You can try this:
list1 = ['GERMANY','FRANCE','SPAIN','PORTUGAL','UK']
list2 = ['ERMANY','FRANCE','SPAN','PORTUGAL','K']
new = [a for a, b in zip(list2, list1) if len(a) < len(b)]

Python "join" on both sides of strings?

l = ['1','2','3']
goal = ['<li>1</li>','<li>2</li>']
How can I get goal from l?
I'm playing with list comprehensions but it's messy!
Try string formatting and list comprehension, like so.
goal = ['<li>{0}</li>'.format(x) for x in l]
Two options using str.format():
goal = map('<li>{0}</li>'.format, l)
... or...
goal = ['<li>{0}</li>'.format(x) for x in l]
Note that on Python 3.x map() will return an iterator instead of a list, so if you want a list you would need to use list(map(...)).
With string.format method
goal = ['<li>{0}</li>'.format(sym) for sym in l]

Tokenizing blocks of code in Python

I have this string:
[a [a b] [c e f] d]
and I want a list like this
lst[0] = "a"
lst[1] = "a b"
lst[2] = "c e f"
lst[3] = "d"
My current implementation that I don't think is elegant/pythonic is two recursive functions (one splitting with '['
and the other with ']' ) but I am sure it can be
done using list comprehensions or regular expressions (but I can't figure out a sane way to do it).
Any ideas?
Actually this really isn't a recursive data structure, note that a and d are in separate lists. You're just splitting the string over the bracket characters and getting rid of some white space.
I'm sure somebody can find something cleaner, but if you want a one-liner something like the following should get you close:
parse_str = '[a [a b] [c e f] d]'
lst = [s.strip() for s in re.split('[\[\]]', parse_str) if s.strip()]
>>>lst
['a', 'a b', 'c e f', 'd']
Well, if it's a recursive data structure you're going to need a recursive function to cleanly navigate it.
But Python does have a tokenizer library which might be useful:
http://docs.python.org/library/tokenize.html
If it's a recursive data structure, then recursion is good to traverse it. However, parsing the string to create the structure does not need to be recursive. One alternative way I would do it is iterative:
origString = "[a [a b] [c [x z] d e] f]".split(" ")
stack = []
for element in origString:
if element[0] == "[":
newLevel = [ element[1:] ]
stack.append(newLevel)
elif element[-1] == "]":
stack[-1].append(element[0:-1])
finished = stack.pop()
if len(stack) != 0:
stack[-1].append(finished)
else:
root = finished
else:
stack[-1].append(element)
print root
Of course, this can probably be improved, and it will create lists of lists of lists of ... of strings, which isn't exactly what your example wanted. However, it does handle arbitrary depth of the tree.

Categories