python sort list by substr - python

I would like to sort a list by a substr of the contents.
Imaginbe the following list and I would like it to be sorted by the number after the '-':
>>> lst = ['ABC-789','DEF-123','GHI-456']
>>> sorted(lst,key=lambda x=lst.split('-') x[1])
This gives me:
sorted(lst, key=lambda x=lst.split('-');x[1])
^
SyntaxError: expression cannot contain assignment, perhaps you meant "=="?
How can I achieve this?

This should work:
sorted(lst, key=lambda x: int(x.split('-')[1]))
Output:
['DEF-123', 'GHI-456', 'ABC-789']

Consider this corrected version:
lst = ['ABC-789','DEF-123','GHI-456']
lst = sorted(lst,key=lambda x: int(x.split('-')[1]))
print(lst) # ['DEF-123', 'GHI-456', 'ABC-789']
You had two issues here. First, your lambda syntax was off, and you want lambda x: <expr in x>. Second, since you want to sort numerically, after extracting the string to the right of the hyphen, you also should be casting to integer. Coincidentally, you can get away with this now, because all numbers are the same text width (3 digits). But, should the numbers not all be the same width, sorting by text might not give a numerical sort.

lst = ['ABC-789','DEF-123','GHI-456']
lst.sort(key=lambda x:x.split('-')[1])
print(lst)
Corrected the lambda and split syntax. Also, I have used the list.sort method instead of sorted in case the original list needs to be sorted and changed.

Related

How to sort python list based on its element that is a tuple at index zero [0]

I have a python list right here
my_list = [("ww","hello"),("www","world"),("w","sardines")]
So I wanted to sort this list based on the length value of the first index of the tuple element which is as you can see there is the letter "w". To be more specific the output should be like this
my_list = [("w","sardines"),("ww","hello"),("www","world")]
I've searched many sorting techniques for this but I find those with for example a string element only. I was thinking of using a sorting algorithm for this like bubble sort, merge sort, insertion or any other sorting algorithm... but I think I am lost in that part and also I think that there is a better way to do this without even using a sorting algorithm. I feel like there's a simpler way like just calling a .sort() function.
Thank you so much for your help! Glad to ask questions here in this great community! Thank you!
Try this:
my_list = [("ww","hello"),("www","world"),("w","sardines")]
def take_el(elem):
return len(elem[0])
sorted(my_list, key=take_el)
or with lambda
sorted(my_list, key = lambda x: len(x[0]))
Use this simple technique to sort on the basis of 1st element in tuple:
sorted(my_list, key=lambda x: len(x[0]))
Change x[0] to x[1] to sort the list using the length of 2nd tuple element and so on..
my_list = [("ww","hello"),("www","world"),("w","sardines")]
listOrder = []
newList = []
for i in my_list:
listOrder.append(int(len(i[0])))
listOrder.sort()
for i in listOrder:
for j in my_list:
if i == len(j[0]):
newList.append(j)
print(newList)
This will also help.
use sorted where x is the tuple and x[n] is the slice
my_list = [("ww","hello"),("www","world"),("w","sardines")]
result = sorted(my_list, key = lambda x: x[0])
print(result)

add letter to string at specific position in loop (problem with sort) [duplicate]

This question already has answers here:
Is there a built in function for string natural sort?
(23 answers)
Closed 3 years ago.
I have a problem with sort. Want to sort the list like
['asd_1qwer', 'asd_14qwer', 'asd_26qwer', 'asd_5qwer']
I found out that i need to add zeros to 1 and 5.
['asd_01qwer', 'asd_05qwer', 'asd_14qwer', 'asd_26qwer']
Dont know how to add it to right position because asd is not static.
list = ['asd_14qwer','asd_5qwer','asd_26qwer','asd_1qwer']
list.sort()
for i in list:
tempo = i.split('_')[-1].split('qwer')[0]
if len(tempo) == 1:
i[:4] + '0' + i[4:]
Edit
Need to add 0 to 1-9 and qwer list constant over all labels.
Actually, if your goal is to sort the list according to the numerical part of the strings, you don't need to zero-pad these numerical part, you just need to provide key function to sort() that extracts the numeric part as an integer:
l = ['asd_14qwer','asd_5qwer','asd_26qwer','asd_1qwer']
l.sort(key=lambda x: int(x.split('_')[-1].rstrip('qwer')))
Please note that this code does not depend on the characters preceding _, only on the fact that the numerical part is between _ and qwer.
You can sort also without adding zeros:
list = ['asd_14qwer','asd_5qwer','asd_26qwer','asd_1qwer']
list.sort(key=lambda i: int(i[(i.index('_') + 1):-4]))
print(list)
Output:
['asd_1qwer', 'asd_5qwer', 'asd_14qwer', 'asd_26qwer']
you can use:
my_list.sort(key=lambda x: int(x[4:][:-4]))
or you can use a regular expression:
import re
my_list.sort(key=lambda x: int(re.search(r'\d+', x).group()))
for i in range(len(list)):
if len(list[i])==9:
list[i] = list[i][:4]+'0'+list[i][4:]
This will add the zeroes at the required places in the list
a 'natural sort' perhaps
import re
def natsort(lst):
"""natural sort"""
lst = [str(i) for i in lst]
import re
convert = lambda text: int(text) if text.isdigit() else text
a_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
return sorted(lst, key=a_key)
lst = ['asd_1qwer', 'asd_14qwer', 'asd_26qwer', 'asd_5qwer']
natsort(lst)
Out[3]: ['asd_1qwer', 'asd_5qwer', 'asd_14qwer', 'asd_26qwer']
Please don't shadow build-in names. I renamed list to my_list below. :)
Also, based on your answers in the comments, your approach was mostly correct, but you don't need to add padding 0 if you're sorting with only numbers - you just need to parse that part as a number! No matter the length - 3, 21, or 111, it will sort correctly then.
sort function has a parameter key where you can set what should be used to sort the elements in the list - that's where we need to put our snippet that extracts and parses the number:
my_list = ['asd_14qwer','asd_5qwer','asd_26qwer','asd_1qwer']
my_list.sort(key=lambda word: int(word.split('_')[-1].split('qwer')[0]))
As you can see, the snippet is similar to what you tried - I just wrapped it in the int call. :)
Result:
['asd_1qwer', 'asd_5qwer', 'asd_14qwer', 'asd_26qwer']

How to get few specific strings from a list of string?

I have a list of strings and a function getVowel.
This function return the number of vowels present in the string.
Here is the sample code.
s = "hello ,this is a string"
no = getVowel(s)
lis = []
lis.append(s)
suppose I have got n no of string in the list lis.
How can I get the top 3 string with maximum no of vowels in them.
sorted(lis, key=lambda x:getVowel(x), reverse=True)[:3]
Something like that. BTW, per Python code conventions the correct name of the function should be get_vowel.
based on this answer:
https://stackoverflow.com/a/9887456/4671300
from heapq import nlargest
results = nlargest(3, lis, key=getVowel)
Assuming your function getVowel is indeed working, try the following:
sorted(lis, key=lambda x: getVowel(x), reverse=True)[:3]
sorted documentation : https://docs.python.org/3.6/library/functions.html?highlight=sorted#sorted
It would be more efficient to take the last three elements from the sorted list rather than reversing it, then taking the first three.
To do this, just index with [-3:] as so:
sorted(lis, key=lambda I: getVowel(i))[-3:]

sorting list of a sentence and number

I have checked several of the answers on how to sort lists in python, but I can't figure this one out.
Let's say I have a list like this:
['Today is a good day,1', 'yesterday was a strange day,2', 'feeling hopeful,3']
Is there a way to sort by the number after each sentence?
I am trying to learn this stuff on my own, so I tried stuff like:
def sortMyList(string):
return len(string)-1
sortedList = sorted(MyList, key=sortMyList())
But of course it doesn't work becaue sortMyList expects one parameter.
Since no one has commented on your coding attempts so far:
def sortMyList(string):
return len(string)-1
sortedList = sorted(MyList, key=sortMyList())
You are on your way, but there are a few issues. First, the key argument expects a function. That function should be sortMyList. sortMyList() would be the result of calling a function - and besides, your function has a parameter (as it should), so calling it with no arguments wouldn't work. Just refer to the function itself.
sortedList = sorted(MyList, key=sortMyList)
Next, you need to tell sorted what is actually being compared when you compare two strings. len(string)-1 gets the length of the string and subtracts one. This would have the effect of sorting the strings by their length, which isn't what you're looking for. You want the character in the string at that index, so sorted will look at all those characters to form a basis for comparison.
def sortMyList(string):
return string[len(string)-1]
Next, you can use a negative index instead of calculating the length of the string, to directly get the last character:
def sortMyList(string):
return string[-1]
Next, we'd like to handle multi-digit numbers. It looks like there's a comma right before the number, so we'll split on that, starting from the right (in case the sentence itself has a comma). We only need the first split, so we'll specify a maxsplit of 1:
def sortMyList(string):
return string.rsplit(',', maxsplit=1)[1]
This will run into a problem: these "numbers" are actually still strings, so when you compare them, it will do so alphabetically, putting "10" before "2" and so on. To fix this, turn the number into an integer before returning it:
def sortMyList(string):
return int(string.rsplit(',', maxsplit=1)[1])
Putting it all together:
def sortMyList(string):
return int(string.rsplit(',', maxsplit=1)[1])
sortedList = sorted(MyList, key=sortMyList)
You can do this
>>> sorted(l, key=lambda x : int(x.split(',')[-1]))
['Today is a good day,1', 'yesterday was a strange day,2', 'feeling hopeful,3']
>>>
This would also work if you happen to have numbers in your string that have more than one digit
>>> l = ['Today is a good day,12', 'yesterday was a strange day,21', 'feeling hopeful,23']
>>> sorted(l, key=lambda x : int(x.split(',')[1]))
['Today is a good day,12', 'yesterday was a strange day,21', 'feeling hopeful,23'] # still works
>>> sorted(l, key=lambda x : x[-1])
['yesterday was a strange day,21', 'Today is a good day,12', 'feeling hopeful,23'] # doesn't work in this scenario
This worked for me:
sorted(myList, key=lambda x: x[-1])
If you need to go into double digits:
sorted(myList, key=lambda x: int(x.split(',')[1]))

Sorting a list using two keys

I have a list of strings which i want to sort according to number of dots(.) in the given string and if the number of dots in those strings is equal i want them to be sorted by their length.(Both in descending order should not be a problem anyway)
The first part could be implemented easily
given_list.sort(key=dots,reverse=True)
dots function is implemented and it works fine.
This is where i am stuck as I am unable to sort the already sorted list according to their lengths if the number of dots is equal.
Which leads me to think i should somehow customize the key parameter using lambda, but it does not really work as it should , but it does in the case of nested lists or dictionaries .
how do i get this done?
You can pass in a custom lambda function to the sorted method as the sorting key.
In this case, I use a lambda x: (x.count("."), len(x)), which will create a composite key of count and length, and sort accordingly:
>>> given_list = ["e.x.a", "m.p.l.e", "ex.am.ple"]
>>> sorted(given_list, key=lambda x: (x.count("."), len(x)))
['e.x.a', 'ex.am.ple', 'm.p.l.e']
>>> sorted(given_list, key=lambda x: (x.count("."), len(x)), reverse=True)
['m.p.l.e', 'ex.am.ple', 'e.x.a']
Since you are using .sort, you can do the same here as well to sort the list in-place:
>>> given_list = ["e.x.a", "m.p.l.e", "ex.am.ple"]
>>> given_list.sort(key=lambda x: (x.count("."), len(x)), reverse=True)
>>> given_list
['m.p.l.e', 'ex.am.ple', 'e.x.a']

Categories

Resources