1

Using Python 3, I have a list of the form

ls = ["a", "b_0", "b_1", "b_2", "c", "d_0", "d_1"]

I have to find out the maximum number after "b_". In this case, the desired output is 2.

I came up with something like that:

import re
p = re.compile("b_(\d+)")
nums = [int(p.match(l).group(1)) for l in ls if p.match(l) is not None]
res_max = max(nums)

But I don't like the repetition of p.match two times.

What is the most pythonic way of achieving this?

The maximum number after d_ is not guaranteed to be less than the maximum number after b_

I specifically need to find out the maximum number after the "b_" prefix. I am not interested in the maximum number after any other prefixes

3
  • Most Pythonic way might be without using any modules or imports. Commented Sep 5, 2021 at 13:07
  • How about the first element in the list "a"? Or do you mean to just ignore anything that has no "b_" in the prefix? Commented Sep 5, 2021 at 13:09
  • @NielGodfreyPonciano ignore anything that has no b_ as a prefix Commented Sep 5, 2021 at 13:11

9 Answers 9

2

Another way:

>>> max(int(i.split("_")[-1]) for i in ls if i.startswith("b_"))
2
Sign up to request clarification or add additional context in comments.

Comments

2

If you don't like repetition, you can use walrus operator :=

import re

ls = ["a", "b_0", "b_1", "b_2", "c", "d_0", "d_1"]

p = re.compile(r"b_(\d+)")

max_num = max(int(m[1]) for l in ls if (m := p.match(l)))
print(max_num)

Prints:

2

Comments

1

Something like...

>>> max([int(i.split('_')[-1]) for i in ls if i.split('_')[-1].isdigit()])
2
>>> 

4 Comments

I think you also need and i[0]=="b"
@not_speshal It doesn't need to be I gues.
The number in d is not guaranteed to be less than the number in b
@robertspierre Yeap! that's what my code does :P
1

You can try:

>>> max([int(i.split('_')[1]) for i in ls if i.split('_')[0] == 'b'])
2

1 Comment

I'm agree with you but I prefer use '_' as delimiter because I guess a, b, c, d are just example. I can use startswith
1

In such case, expand the list comprehension into explicit list appending:

import re
p = re.compile("b_(\d+)")

nums = []
for l in ls:
    m = p.match(l)
    if m is not None:
        nums.append(int(m.group(1))

res_max = max(nums)

Comments

1

You can try list comprehension-

ls = ["a", "b_0", "b_1", "b_2", "c", "d_0", "d_1"]

res = max([int(string.split('_')[1]) for string in ls if string.startswith('b_')])

print(res) # 2

Comments

1

This could another way

ls = ["a", "b_0", "b_1", "b_2", "c", "d_0", "d_1"]
res_max = max([int(i.split('_')[1]) for i in ls if i[0] == 'b'])
print(res_max)

Output: 2

Comments

0

One way would be nested comprehensions:

import re
p = re.compile("b_(\d+)")
nums = [
    int(m.group(1))
    for m in (p.match(l) for l in ls)
    if m is not None
]
res_max = max(nums)

Comments

0

Heres another way of doing it using re.search()

    import re

    ls = ["a", "b_0", "b_1", "b_2", "c", "d_0", "d_1"]
    pattern = r'b_(\d+)'

    lst = [res.group(1) for i in ls if (res := re.search(pattern, i))]
    print(max(lst))

Output:

    2

In the 6th line it's checking every element in the list ls if it matches the pattern, then adds the first group of the matching string (which is the number) to the list lst.

The part res := re.search(pattern, i) is assigning the value of re.search(pattern, i) to the variable res and at the same time as its checking if it's None then the if statement won't activate, if it has a value then the if statement will get activated. This is thanks to the 'Walrus Operator' :=.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.