3

Problem

I have next list:

a = (('_a_1', '_a_2'), [0.3, 0.6]) 
b = (('_a_3', '_a_4'), [0.15, 0.56]) 
c = (('_a_5', '_a_6'), [0.22, 0.6])

l = [a, b, c]

What I wan't: choose first tuples of list and remove _a_ labels. Result:

[['1','2'],['3','4'],['5','6']]

What I tried

I know I can do it using list comprehension. But I can't comprehend it :D What I'm trying:

[ el.replace('_a_','') for m in l for el in m[0]]

result:

['1', '2', '3', '4', '5', '6']

I think it is closed to right solution. Just add something like:

[ [el.replace('_a_','') for m in l] for el in m[0]]

But it doesn't work...

Mikhail_Sam
  • 10,602
  • 11
  • 66
  • 102

5 Answers5

2

Here is one way using str.split:

a = (('_a_1', '_a_2'), [0.3, 0.6]) 
b = (('_a_3', '_a_4'), [0.15, 0.56]) 
c = (('_a_5', '_a_6'), [0.22, 0.6])

res = [[i.split('_')[-1], j.split('_')[-1]] for (i, j), k in [a, b, c]]

# [['1', '2'], ['3', '4'], ['5', '6']]

You can also use str.replace:

res = [[i.replace('_a_', ''), j.replace('_a_', '')] for (i, j), k in [a, b, c]]

As suggested by @Ev.Kounis, you can also write this functionally:

res = [list(map(lambda x: x.rsplit('_', 1)[-1], k)) for k, _ in [a, b, c]]

Nested list comprehensions require specific ordering, intuitive to some but not to others. The above solutions avoid them altogether.

jpp
  • 159,742
  • 34
  • 281
  • 339
  • 1
    or `[list(map(lambda x: x.rsplit('_', 1)[-1], k)) for k, _ in [a, b, c]]` which might be slightly faster. Nevertheless, +1 – Ma0 Apr 16 '18 at 12:32
  • fyi, the solution using `map` is more than two times slower. – Arne Apr 16 '18 at 12:44
  • @Arne, I'm not surprised, but thank you for noting. I guess it's good to see different ways while you're learning. – jpp Apr 16 '18 at 12:46
1

You were close:

a = (('_a_1', '_a_2'), [0.3, 0.6]) 
b = (('_a_3', '_a_4'), [0.15, 0.56]) 
c = (('_a_5', '_a_6'), [0.22, 0.6])

l = [a, b, c]

[ [el.replace('_a_','') for el in tup[0]] for tup in l]
# [['1', '2'], ['3', '4'], ['5', '6']]
Thierry Lathuille
  • 23,663
  • 10
  • 44
  • 50
  • Does it mean, If I add inner brackets I must `inverse` logic: In usual nested loops every inner loop adds at the end, but here inner loop added at the left? – Mikhail_Sam Apr 16 '18 at 12:27
0
res=[[j.replace("_a_","") for j in i[0]]  for i in l]
#OUT
[['1', '2'], ['3', '4'], ['5', '6']]
Roushan
  • 4,074
  • 3
  • 21
  • 38
  • Generally, answers are much more helpful if they include an explanation of what the code is intended to do, and why that solves the problem without introducing others. – Neuron Apr 16 '18 at 13:20
  • code seems self explanatory, nothing much complicated otherwise putted the explanation :) – Roushan Apr 16 '18 at 13:22
  • Well, you can explain why the original attempt failed and how your code fixed the issue. SO is no for sharing working code, but learning why something is not working! Cheers – Neuron Apr 16 '18 at 13:26
0

Another way of doing it would be to use the zip function:

a = (('_a_1', '_a_2'), [0.3, 0.6]) 
b = (('_a_3', '_a_4'), [0.15, 0.56]) 
c = (('_a_5', '_a_6'), [0.22, 0.6])

l = [[elem[0][-1],elem[1][-1]] for elem in list(zip(a,b,c))[0]]

print(l)

Output:

[['1', '2'], ['3', '4'], ['5', '6']]
Vasilis G.
  • 7,556
  • 4
  • 19
  • 29
0

You can go with regex without splitting it :

import re
pattern=r'[0-9]+'

print([tuple(map(lambda x:re.search(pattern,x).group(),i[0])) for i in l])

output:

[('1', '2'), ('3', '4'), ('5', '6')]
Aaditya Ura
  • 12,007
  • 7
  • 50
  • 88