Home > Software design >  How to cut substrings of a list like from s[0][i:j] by splitting from dots?
How to cut substrings of a list like from s[0][i:j] by splitting from dots?

Time:11-03

Sorry it's very complicated to tell this in English for me. Here is my problem. I have this list:

s=["2.11", "4.7.0", "1.3", "2.2", "0.1", "1.2.5", "1.3.1", "2.7"]

I want these numbers ordered by from smallest to biggest. But not mathematicallly, not quite. For version numbers concept.

Think them as like version numbers. Not ordinary math. For ordinary math, 2.2>2.11 but for program version numbers concept, it's 2.11>2.2 So I need to somehow order them like that. First thing came in my mind was this. Maybe get those 11, 7, 3, 2 numbers from there that is split from dots. Then compare them, problem is how to get them out? I tried various solutions from stackoverflow. For example 2.11's 11 is this :

print(s[0][2:len(s[0])]) # prints 11

Since this list is actually two dimentional array like you, many solutions don't work for me. Please help. Or am I missing something? Is there a much simpler way to do this?

Expected output is below. Think that this returns from a function:

0.1,1.2.5,1.3,1.3.1,2.2,2.7,2.11,4.7

CodePudding user response:

Use:

s=["2.11", "4.7.0", "1.3", "2.2", "0.1", "1.2.5", "1.3.1", "2.7"]
res = sorted(s, key=lambda x: tuple(map(int, x.split("."))))
print(res)

Output

['0.1', '1.2.5', '1.3', '1.3.1', '2.2', '2.7', '2.11', '4.7.0']

The idea is to compare the strings using the key parameter of sorted, from the documentation (emphasis mine):

key specifies a function of one argument that is used to extract a comparison key from each element in iterable (for example, key=str.lower). The default value is None (compare the elements directly).

In this case the key parameter splits the string by "." and convert each sub string to a an integer, for example:

"0.1" -> (0, 1)
"2.2" -> (2, 2)
"2.11" -> (2, 11)

As an alternative use:

res = sorted(s, key=lambda x: [int(xi) for xi in x.split(".")])

In here you can find more ideas for key parameter of sorted (how to compare version numbers in Python). If the version is PEP440 compliant you could use packaging.version.parse:

from packaging.version import parse

s = ["2.11", "4.7.0", "1.3", "2.2", "0.1", "1.2.5", "1.3.1", "2.7"]
res = sorted(s, key=parse)
print(res)

Output

['0.1', '1.2.5', '1.3', '1.3.1', '2.2', '2.7', '2.11', '4.7.0']

CodePudding user response:

So this, should work

# as version numbers, so 2.7.2 is less than 2.7.11 for example.
s = ["2.11", "4.7.0", "1.3", "2.2", "0.1", "1.2.5", "1.3.1", "2.7"]

# sort the list of versions numbers
s.sort(key=lambda x: list(map(int, x.split('.'))))
print(s)

as of python>=3.8 I think that map returns an iterator so we need to cast it into a list manually

CodePudding user response:

One way using distutils.version.LooseVersion.

If they are like version, let them be handled as versions.

from distutils.version import LooseVersion

sorted(s, key=LooseVersion)

Output:

['0.1', '1.2.5', '1.3', '1.3.1', '2.2', '2.7', '2.11', '4.7.0']
  • Related