Remove ' from python list - python

I have a list, that looks like this in python:
ex = ['(1..3),(5..8)']
I need to get out the list like this:
[(1, 3), (5, 8)]
I tried using the replace function, but could only get like
['(1, 3), (5,8)'] and could not lose the ' marks.
Hope someone can help me.
Thanks

import ast
ex = ['(1..3),(5..8)']
list(ast.literal_eval(ex[0].replace('..', ',')))
# returns [(1, 3), (5, 8)]
ast.literal_eval is safe. eval is not.
For your updated question:
ex2 = ['(2..5)', '(7..10)']
[ast.literal_eval(a.replace('..', ',')) for a in ex2]
# returns [(2, 5), (7, 10)]

Look like some regex task.
>>> import re
>>> ex = ['(1..3),(5..8)']
>>> re.findall(r'\((\d+)\.\.(\d+)\)', ex[0])
[('1', '3'), ('5', '8')]
>>> # if you want tuple of numbers
... [tuple(map(int, x)) for x in _]
[(1, 3), (5, 8)]

This became uglier than I expected:
In [26]: ex = ['(1..22),(3..44)']
In [27]: [tuple([int(i) for i in s.strip('()').split('..')])
for s in ex[0].split(',')]
Out[27]: [(1, 22), (3, 44)]

if your format is constant, this should work :
>>> n = list(eval(ex[0].replace("..",",")))
>>> n
[(1, 3), (5, 8)]
UPDATE :
using literal eval ( safer ):
import ast
result = list(ast.literal_eval(ex[0].replace("..",",")))

Related

python 2.7 unique calculation issue

Using Python 2.7, I have a list, and each element in the list is a (sub-list) -- a list of tuples. I want to remove the duplicate sub-list, I post input and expected output. I tried to use set, but there is error said list is not hashable. Anyone have good elegant code solutions? Thanks.
a=[[(1,2),(1,3)],
[(1,3),(1,2)],
[(1,2),(1,3)]]
# expect output
'''
a=[[(1,2),(1,3)],
[(1,3),(1,2)]]
'''
Try this! This is the simplest method.
a = [[(1,2),(1,3)],
[(1,3),(1,2)],
[(1,2),(1,3)]]
print [list(i) for i in set(map(tuple, a))]
[[(1, 3), (1, 2)], [(1, 2), (1, 3)]] //output
The above one is without any library support and also the ordering of the original list can't be ensured.
If you want to preserve the order of the list, then go for collections library.
from collections import OrderedDict
a = [[(1,2),(1,3)],
[(1,3),(1,2)],
[(1,2),(1,3)]]
print map(list, OrderedDict.fromkeys(map(tuple, a)))
[[(1, 2), (1, 3)], [(1, 3), (1, 2)]] //output
I think you can use a set, something like below
a=[[(1,2),(1,3)],
[(1,3),(1,2)],
[(1,2),(1,3)]]
unique_list = [list(x) for x in set(tuple(x) for x in a)]
print unique_list
Output:
[[(1, 3), (1, 2)], [(1, 2), (1, 3)]]
See working repl here - https://repl.it/EinE/1

How do I return a list of tuples with each unique string and its count given a list of strings?

Not sure where to start...
item() gives a dictionary and I don't want that.
I would say I need to loop through the list....
Please someone give me some hints so I can get started!
EDIT:
count_of_names(names)
counts_of_names(['John', John', 'Catherine', 'John', 'Christopher', 'Catherine']'
output:
[('Catherine', 2), ('Christopher', 1), ('John', 3)]
This is a hard way to do it:
x = [1,3,2,5,6,6,3,2]
x_tuple = []
y = set(x)
for i in y:
x_tuple.append((i,x.count(i)))
print(x_tuple)
You may use collections.Counter() to achieve this. Example:
>>> x = [1,2,3,4,1,1,2,3]
>>> my_list = Counter(x).items()
>>> my_list
[(1, 3), (2, 2), (3, 2), (4, 1)]
# In order to sort the list base based on value of tuple at index `1` and then index `0`
>>> sorted(my_list, key=lambda x: (x[1], x[0]))
[(4, 1), (2, 2), (3, 2), (1, 3)]
Use set and list comprehension:
def counts_of_names(names):
return [(name, names.count(name)) for name in set(names)]

How do I organise a nested list representing coordinate-values to a coordinate-list

I would like to change my data-structure that get from my data-files in such a way that I get a list of all coordinate-values for every coordinates (so a list for all coordinates filled with values)
e.g.
for i in range (files):
open file
file_output = [[0,4,6],[9,4,1],[2,5,3]]
second loop
file_output = [[6,1,8],[4,7,3],[3,7,0]]
to
coordinates = [[0,6],[4,1],[6,8],[9,4],[4,7],[1,3],[2,3],[5,7],[3,0]]
It should be noted that I use over 1000 files of this format, which I should merge.
You could also explore the built-in zip() function
>>> l = []
>>> for k,v in zip(a,b):
l.append(zip(k,v))
>>> print l
[[0,6],[4,1],[6,8],[9,4],[4,7],[1,3],[2,3],[5,7],[3,0]]
>>> a = [[0,4,6],[9,4,1],[2,5,3]]
>>> b = [[6,1,8],[4,7,3],[3,7,0]]
>>> from itertools import chain
>>> zip(chain(*a),chain(*b))
[(0, 6), (4, 1), (6, 8), (9, 4), (4, 7), (1, 3), (2, 3), (5, 7), (3, 0)]
>>>
This should be useful.
[zip(i,j) for i in a for j in b]
However it provides list of tuples, which should satisfy your needs.
If there will only be two lists, you can use this as well.
[[i, j] for i in a for j in b]

Is it possible to include mutiple equations in a lambda function

I'm trying to include multiple operations in the lambda function with variables that have different lengths, i.e. something like:
$ serial_result = map(lambda x,y:(x**2,y**3), range(20), range(10))
but this doesn't work. Could someone tell me how to get around this?
I understand that:
$ serial_result = map(lambda x,y:(x**2,y**3), range(0,20,2), range(10))
works because the arrays of "x" and "y" have the same length.
If you want the product of range items you can use itertools.product :
>>> from itertools import product
>>> serial_result = map(lambda x:(x[0]**2,x[1]**3), product(range(20), range(10)))
If you want to pass the pairs to lambda like second case you can use itertools.zip_longest (in python 2 use izip_longest)and pass a fillvalue to fill the missed items,
>>> from itertools import zip_longest
>>> serial_result = map(lambda x:(x[0]**2,x[1]**3), zip_longest(range(20), range(10),fillvalue=1))
Note that if you are in python 2 you can pass multiple argument to lambda as a tuple :
>>> serial_result = map(lambda (x,y):(x**2,y**3), product(range(20), range(10)))
See the difference of izip_longest and product in following example :
>>> list(product(range(5),range(3)))
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2), (3, 0), (3, 1), (3, 2), (4, 0), (4, 1), (4, 2)]
>>> list(zip_longest(range(5),range(3)))
[(0, 0), (1, 1), (2, 2), (3, None), (4, None)]
>>> list(zip_longest(range(5),range(3),fillvalue=1))
[(0, 0), (1, 1), (2, 2), (3, 1), (4, 1)]
It sounds like you may be confused as to how exactly you want to use all the values in these two variables. There are several ways combine them...
If you want a result for every combination of an element in a and an element in b: itertools.product(a, b).
If you want to stop once you get to the end of the shorter: zip(a, b)
If you want to continue on until you've used all of the longest: itertools.zip_longer(a, b) (izip_longer in python 2). Once a runs out of elements it will be filled in with None, or a default you provide.

How to enumerate a range of numbers starting at 1

I am using Python 2.5, I want an enumeration like so (starting at 1 instead of 0):
[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]
I know in Python 2.6 you can do: h = enumerate(range(2000, 2005), 1) to give the above result but in python2.5 you cannot...
Using Python 2.5:
>>> h = enumerate(range(2000, 2005))
>>> [x for x in h]
[(0, 2000), (1, 2001), (2, 2002), (3, 2003), (4, 2004)]
Does anyone know a way to get that desired result in Python 2.5?
As you already mentioned, this is straightforward to do in Python 2.6 or newer:
enumerate(range(2000, 2005), 1)
Python 2.5 and older do not support the start parameter so instead you could create two range objects and zip them:
r = xrange(2000, 2005)
r2 = xrange(1, len(r) + 1)
h = zip(r2, r)
print h
Result:
[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]
If you want to create a generator instead of a list then you can use izip instead.
Just to put this here for posterity sake, in 2.6 the "start" parameter was added to enumerate like so:
enumerate(sequence, start=1)
Python 3
Official Python documentation: enumerate(iterable, start=0)
You don't need to write your own generator as other answers here suggest. The built-in Python standard library already contains a function that does exactly what you want:
>>> seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1))
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
The built-in function is equivalent to this:
def enumerate(sequence, start=0):
n = start
for elem in sequence:
yield n, elem
n += 1
Easy, just define your own function that does what you want:
def enum(seq, start=0):
for i, x in enumerate(seq):
yield i+start, x
Simplest way to do in Python 2.5 exactly what you ask about:
import itertools as it
... it.izip(it.count(1), xrange(2000, 2005)) ...
If you want a list, as you appear to, use zip in lieu of it.izip.
(BTW, as a general rule, the best way to make a list out of a generator or any other iterable X is not [x for x in X], but rather list(X)).
from itertools import count, izip
def enumerate(L, n=0):
return izip( count(n), L)
# if 2.5 has no count
def count(n=0):
while True:
yield n
n+=1
Now h = list(enumerate(xrange(2000, 2005), 1)) works.
enumerate is trivial, and so is re-implementing it to accept a start:
def enumerate(iterable, start = 0):
n = start
for i in iterable:
yield n, i
n += 1
Note that this doesn't break code using enumerate without start argument. Alternatively, this oneliner may be more elegant and possibly faster, but breaks other uses of enumerate:
enumerate = ((index+1, item) for index, item)
The latter was pure nonsense. #Duncan got the wrapper right.
>>> list(enumerate(range(1999, 2005)))[1:]
[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]
h = [(i + 1, x) for i, x in enumerate(xrange(2000, 2005))]
Ok, I feel a bit stupid here... what's the reason not to just do it with something like
[(a+1,b) for (a,b) in enumerate(r)] ? If you won't function, no problem either:
>>> r = range(2000, 2005)
>>> [(a+1,b) for (a,b) in enumerate(r)]
[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]
>>> enumerate1 = lambda r:((a+1,b) for (a,b) in enumerate(r))
>>> list(enumerate1(range(2000,2005))) # note - generator just like original enumerate()
[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]
>>> h = enumerate(range(2000, 2005))
>>> [(tup[0]+1, tup[1]) for tup in h]
[(1, 2000), (2, 2001), (3, 2002), (4, 2003), (5, 2004)]
Since this is somewhat verbose, I'd recommend writing your own function to generalize it:
def enumerate_at(xs, start):
return ((tup[0]+start, tup[1]) for tup in enumerate(xs))
I don't know how these posts could possibly be made more complicated then the following:
# Just pass the start argument to enumerate ...
for i,word in enumerate(allWords, 1):
word2idx[word]=i
idx2word[i]=word

Categories