I have a list of coordinates like:
[44.64,-123.11;38.91,-121.99;40.35,-122.28;43.21,-123.36;41.77,-122.58;37.77,-122.42]
I need to sort this list. Any suggestions ?
EDIT:
Sorry for not sharing the expected output:
It should be [44.64,-123.11;43.21,-123.36;41.77,-122.58;40.35,-122.28;38.91,-121.99;37.77,-122.42]
li = [44.64,-123.11;38.91,-121.99;40.35,-122.28;43.21,-123.36;41.77,-122.58;37.77,-122.42]
Your "list" looks more like a string, with ";" and "," to separate 2D points and their values. I imagine that you want a list of tuples, that represent the x and y coordinates? So first you need to split your string into a list
li = li.split(';')
Now you have a list of strings, that you need to split into pairs of float values. You can do that with two list comprehensions
li = [(float(a.split(',')[0]), float(a.split(',')[1])) for a in li]
Now you have a list of coordinates that you could sort in some way. Maybe smallest x first or something. Use Python's sorted build-in function to do that, e.g.
sorted_li = sorted(li, key=lambda x: x[0])
The docs are here, read them.
https://docs.python.org/3.6/library/functions.html#sorted
Related
I am creating a list in python in the following way:
new_points = [None] * 25
for point in points:
new_points[point.id] = point
I am wondering if this can be achieved by Python one-line list comprehension. Please note that each point has a unique id. Hence two points can never have same ids.
This sounds like you want to sort the list rather than use a comprehension.
new_points = sorted(points, key=lambda x:x.id)
The sorted function takes an iterable and a key function and returns a list. In this case the key function only needs to get the id.
I don't know of any way to populate random locations in a list with a one-liner. But if all you want is to be able to find a point by its id, you could use a dict in stead of a list:
new_points = {p.id: p for p in points}
Currently I'm trying to sort a list of files which were made of version numbers. For example:
0.0.0.0.py
1.0.0.0.py
1.1.0.0.py
They are all stored in a list. My idea was to use the sort method of the list in combination with a lambda expression. The lambda-expression should first remove the .py extensions and than split the string by the dots. Than casting every number to an integer and sort by them.
I know how I would do this in c#, but I have no idea how to do this with python. One problem is, how can I sort over multiple criteria? And how to embed the lambda-expression doing this?
Can anyone help me?
Thank you very much!
You can use the key argument of sorted function:
filenames = [
'1.0.0.0.py',
'0.0.0.0.py',
'1.1.0.0.py'
]
print sorted(filenames, key=lambda f: map(int, f.split('.')[:-1]))
Result:
['0.0.0.0.py', '1.0.0.0.py', '1.1.0.0.py']
The lambda splits the filename into parts, removes the last part and converts the remaining ones into integers. Then sorted uses this value as the sorting criterion.
Have your key function return a list of items. The sort is lexicographic in that case.
l = [ '1.0.0.0.py', '0.0.0.0.py', '1.1.0.0.py',]
s = sorted(l, key = lambda x: [int(y) for y in x.replace('.py','').split('.')])
print s
# read list in from memory and store as variable file_list
sorted(file_list, key = lambda x: map(int, x.split('.')[:-1]))
In case you're wondering what is going on here:
Our lambda function first takes our filename, splits it into an array delimited by periods. Then we take all of the elements of the list, minus the last element, which is our file extension. Then we apply the 'int' function to every element of the list. The returned list is then sorted by the 'sorted' function according to the elements of the list, starting at the first with ties broken by later elements in the list.
I've got list like this z = ['aaaaaa','bbbbbbbbbb','cccccccc'] i would like to cut off first 6 chars from all elements and if element is empty not to put in another list. So I made this code:
[x[6:] if x[6:] is not '' else pass for x in z]
I've tried with
pass
continue
and still syntax error. Maybe someone could help me with it? thanks
Whenever you need to filter items from a list, the condition has to be at the end. So you need to filter the empty items, like this
[x[6:] for x in z if x[6:] != ""]
# ['bbbb', 'cc']
Since, an empty string is falsy, we can write the same condition succinctly as follows
[x[6:] for x in z if x[6:]]
As an alternative, as tobias_k suggested, you can check the length of the string like this
[x[6:] for x in z if len(x) > 6]
If you are learning to do with lambda(not an official link), you should try with map and filter like this:
filter(None, map(lambda y: y[6:], x))
Here, the map(lambda y: y[6:], x) will keep only strings from 7th character and replace other smaller strings with Boolean 'False'. To remove all these 'False' values from the new list, we will use filter function.
You can take this only for learning purposes as this is downright ugly when Python's PEP8 is considered. List comprehension is the way to go like mentioned above.
[y[6:] for y in x if y[6:]]
Or the traditional for loop as
output = []
for y in x:
if isinstance(y, str) and y[6:]:
output.append(y[6:])
Please note that even though the traditional way looks bigger, it can add more values(like here, taking only the strings from the list if the list has other data types such as lists, tuples, dictionaries, etc)
So I would suggest either to stick with list comprehensions for simple controlled lists or the traditional way for controlled output
I have a list of lists that looks like this:
[['10.2100', '0.93956088E+01'],
['11.1100', '0.96414905E+01'],
['12.1100', '0.98638361E+01'],
['14.1100', '0.12764182E+02'],
['16.1100', '0.16235739E+02'],
['18.1100', '0.11399972E+02'],
['20.1100', '0.76444933E+01'],
['25.1100', '0.37823686E+01'],
['30.1100', '0.23552237E+01'],...]
(here it looks as if it is already ordered, but some of the rest of the elements not included here to avoid a huge list, are not in order)
and I want to sort it by the first element of each pair, I have seen several very similar questions, but in all the cases the examples are with integers, I don't know if that is why when I use the list.sort(key=lambda x: x[0]) or the sorter, or the version with the operator.itemgetter(0) I get the following:
[['10.2100', '0.93956088E+01'],
['100.1100', '0.33752517E+00'],
['11.1100', '0.96414905E+01'],
['110.1100', '0.25774972E+00'],
['12.1100', '0.98638361E+01'],
['14.1100', '0.12764182E+02'],
['14.6100', '0.14123326E+02'],
['15.1100', '0.15451733E+02'],
['16.1100', '0.16235739E+02'],
['16.6100', '0.15351242E+02'],
['17.1100', '0.14040859E+02'],
['18.1100', '0.11399972E+02'], ...]
apparently what is doing is sorting by the first character appearing in the first element of each pair.
Is there a way of using list.sort or sorted() for ordering this pairs with respect to the first element?
dont use list as a variable name!
some_list.sort(key=lambda x: float(x[0]) )
will convert the first element to a float and comparit numerically instead of alphabetically
(note the cast to float is only for comparing... the item is still a string in the list)
The following code creates a multi dimensional list (not sure if that's the Pythonic was of saying it. PHP guy here)
patterns.append(list(itertools.permutations('1234567',7)))
the value of patterns becomes:
([
[1,2,3,4,5,6,7],
[1,2,3,4,5,7,6], ...
])
What I want is for the result to be like this:
([1,2,3,4,5,6,7], [1,2,3,4,5,7,6]...)
If i try doing:
patterns = list(itertools.permutations('1234567',7))
the result is a list of individual numbers
123445671234576
What am I missing?
Thanks,
You extend() instead of append().
patterns.extend(itertools.permutations('1234567',7))
This also makes list() redundant because extend() works on iterables.
This assumes you are ok with the permutations themselves being tuples. Your question is confusing because you the notation doesn't correspond with what you wrote in words.
If you need to get
([1,2,3,4,5,6,7], [1,2,3,4,5,7,6]...)
than you can use:
from itertools import permutations
patterns = tuple(list(int(y) for y in x) for x in permutations('1234567',7))
OR you can use xrange instead of '1234567' if you need to get numbers:
patterns = tuple(list(x) for x in permutations(xrange(1,8),7))
You can get a tuple of lists with
tuple(list(p) for p in itertools.permutations('1234567', 7))
If you want integers instead of one-element strings, then an easy and general way to do that is
digits = [int(digit) for digit in '1234567']
tuple(list(p) for p in itertools.permutations(digits, 7))