This question already has answers here:
Is there a built in function for string natural sort?
(23 answers)
Closed 22 days ago.
I would like to sort strings by numbers, but keep them in groups. Means, keep Cs, Rs, ... together, but in a numeric sorted order. There are similar questions like here Is there a built in function for string natural sort?, but all of them are dealing with strings starting with the same string. So this is little bit different.
# input
a = ['C2', 'C1', 'R3', 'R21', 'C10', 'R1', 'L1']
# expected output
['C1', 'C2', 'C10', 'R1', 'R3', 'R21', 'L1']
# I tried multiple options, but didn't find the right one.
a.sort(key=lambda x: int(x[1:]))
So how to get the results without creating the special parsing function?
Thanks
You can use a tuple of the letter and number instead of just the number in sort:
>>> a.sort(key=lambda x: (x[0], int(x[1:])))
['C1', 'C2', 'C10', 'L1', 'R1', 'R3', 'R21']
Related
I want to print out from 1 to 1320 like d1,d2,d3,d4 and so on
The command >>> list(range(1320)) will print out like 1,2, 3 etc. so I tried with d(list(range(1320))) but it says NameError: name 'd' is not defined
So my question id how to print the numbers like d1,d2,d3 .....
Maybe I am missing very basic syntax here. Any help?
list(range(1320)) builds a list out of that range of numbers, and when that list is shown in your Python session, it lists the elements separated by commas. [0, 1, 2, ...]
If you want to build a list of d0, d1, d2 etc. you can use a list comprehension.
>>> ['d%s'%i for i in range(1320)]
['d0', 'd1', 'd2', 'd3', ....
But if you actually want to just print those strings separated by commas, you can use join:
>>>> print(', '.join(['d%s'%i for i in range(1320)]))
d0, d1, d2, d3, ...
You can use list comprehension like this:
['d{}'.format(i) for i in range(1320)]
of for Python3.6 and higher:
[f'd{i}' for i in range(1320)]
>>>>['d'+str(i) for i in range(1320)]
This is another way to do the same in one line using basic list comprehension.
Just loop till 1230 and concatenate with 'd'.
I'm constructing dictionaries lists in Python, with aim to iterate through each one individually and concatenate all different combinations. There are three different components to each "product" in a dictionary list:
1) a letter, e.g. 'A' (first part of the product code, unique to each product entry). Let's say the range here is:
['A', 'B', 'C']
2) a letter and number, e.g. 'S2' (2nd part, has several variations...might be 'D3' or 'E5' instead)
3) a period ('.') and a letter, e.g. '.X' (3rd part, unique to each product entry). Let's say the range here is:
['.X', '.Y', '.Z']
Since the 2nd part listed above has the most variations, my starting assumption is to construct dicts lists with the 1st and 3rd parts together, in order to reduce the number of different listsdicts, since they are uniquely paired, e.g. 'A.Z'...but, I would still need to split each entry then insert the 2nd part, between them, via some 'concatenate' command. So, question is: if I have another dict list with all variations of the 2nd part, what function(s) should I use to construct all variants of a product?
The total combination of examples:
ListOne = ['A', 'B', 'C']
ListTwo = ['D3', 'D4', 'D5', 'E3', 'E4', 'E5']
ListThr = ['.X', '.Y', '.Z']
I need to create new dicts lists as concatenations of all three dicts lists, e.g. 'AD3.X', but there are no variants for ListOne vs ListThr, it will always be 'A' matched to '.X' or 'B' and 'C' matched to '.Y'...ListTwo products concatenated between ListOne and ListThr products will need to be iterated so all possible combinations are output as a new dict list e.g.
ListOneNew = ['AD3.X', 'AD4.X', AD5.X', 'AE3.X', 'AE4.X', 'AE5.X']
ListTwoNew = ['BD3.Y', 'BD4.Y', 'BD5.Y', <and so on...>]
For simplicity's sake, should the script have a merged version of ListOne and ListThr e.g.
List = ['A.X', 'B.X', 'C.Z']
and then split & concatenate with ListTwo products, or just have three Lists and concatenate from there?
from itertools import product
result = [a[0] + a[1] + a[2] for a in list(product(DictOne, DictTwo, DictThr))]
With list comprehension
final = sorted([a+b+c for c in DictThr for b in DictTwo for a in DictOne])
Set means to remove duplicate Items. Duplicate is identified by a equals to b.
Can I change equals to to a different predicate? I am trying to do this in Python but any language is fine.
I would like to know if there are any inbuilt set mechanisms to reduce ['aaaa', 'aa', 'b', 'bb', 'c'] to ['aaaa', 'bb' 'c']. Here duplicate is defined by if it is substring of something else. I feel there is a similarity in how duplicates are found. But if it's using hashing then I could be wrong.
I'm trying to write code that can sort a list of lists by an unknown number of keys, with each key having an associated boolean corresponding to whether the sort should be ascending or descending.
I have it working to sort by all keys in ascending or descending order like this:
import operator
def sort2D(table, *params):
table.sort(key=operator.itemgetter(*params), reverse = True)
return table
table = sort2D(table, *listOfKeys)
I'm not sure how to input the boolean values into that function as well though. I get a syntax error when I try to do similar code for a second list of inputs, like this:
import operator
def sort2D(table, *params, *args): #this is the line that causes the syntax error
table.sort(key=operator.itemgetter(*params), reverse = *args)
return table
table = sort2D(table, *listOfKeys, *listOfBools)
I can tell that the error is because I'm misusing *, *params, and *args to input a list into the function, but I don't know how I could input the second list without something that looks similar to that. Is it possible to input the second list into the function that I have, or do I have to do something completely different to accomplish what I want?
edit: An example of my desired input and output would look something like this:
['Smith', 'Bob', 4, 3.75, 'Blue']
['Jones', 'Tom', 17, 0.44, 'Blue']
['Smith', 'John', 3, 2.22, 'Yellow']
['Jones', 'Drew', 5, 6.74, 'Red']
If it were sorted by last name descending and then by integer ascending, then params would be [0, 2] corresponding to the columns and bools would be [True, False]. The output would look like this:
['Smith', 'John', 3, 2.22, 'Yellow']
['Smith', 'Bob', 4, 3.75, 'Blue']
['Jones', 'Drew', 5, 6.74, 'Red']
['Jones', 'Tom', 17, 0.44, 'Blue']
You cannot have two *something parameters to a single function. Nor can you apply multiple reverse= values to a single sort call, anyway.
The only clean, completely general way to use multiple reverse values (without knowing whether the keys potentially being reversed are strings, numbers, tuples, ...), is, unfortunately, to do multiple sort passes (in reverse: the most significant key must be the one on which you sort last).
So...:
def sort2D(table, params, reverses):
for parm, rev in reversed(zip(params, reverses)):
table.sort(key=operator.itemgetter(parm), reverse=rev)
return table
table = sort2D(table, listOfKeys, listOfBools)
If you do know something about the keys (items) you're sorting on, e.g that they're all numbers, you could prepare a single key function to then do a single-pass sort (changing sign to numbers corresponding to a true value for the corresponding reversal bool).
But it's a really challenging problem for general keys -- I can't even think of a way to do it effectively for tuples, for example!-)
And even doing it just for strings would I believe be at least a Google-interview-level question -- "define a function rev such that, for any two strings s1 and s2,
rev(s1) < rev(s2) if and only if s1 > s2
"""
(Actually in this totally general formulation it's harder than I thought when I was jotting it down...!-)
In real life, faced with such a difficult problem, I'd do the multiple sort passes, decree victory, and go home:-)
As a beginner of Python I recently get stuck for a problem of sorting a nested list with specific criteria. I have a nested list like this:
nestedList=[['R2D2','1path1','1path2'],
['R3A1','2path1','2path2'],
['R15L2','3path1','3path2']]
I would like this list to be sorted by the first string in each nested list. The result would look like:
nestedList=[['R15L2','3path1','3path2'],
['R3A1','2paht1','2path2'],
['R2D2','1path1','1path2']]
Currently my solution is only use the sort function with reverse parameter:
nestedList.sort(reverse=True)
I am not sure whether this is safe, because I would like it not sort the list also by the second string.
How could I sort it only by the first string? (e.g. 'R15L2', 'R3A1', etc.)
Thanks a lot for your help!
You want to sort according to a key (the key is the first element of a list):
nestedList.sort(key=lambda x: x[0])
or
import operator as op
nestedList.sort(key=op.itemgetter(0))
a = [['3f','2f','5a'],['5a','0r','7v'],['4r','58v','5l']]
>>> a
[['3f', '2f', '5a'], ['5a', '0r', '7v'], ['4r', '58v', '5l']]
>>> a.sort()
>>> a
[['3f', '2f', '5a'], ['4r', '58v', '5l'], ['5a', '0r', '7v']]
>>> a.sort(reverse=True)
>>> a
[['5a', '0r', '7v'], ['4r', '58v', '5l'], ['3f', '2f', '5a']]
>>>