I wanted to convert the integer of tuple into string of tuple.
For example:
data = [(2,3,4,...),(23,42,54,...),......]
would result in:
d = [('2','3','4',...),('23','42','54',....)......]
Please notice how tuple is big and list is also big.
I tried the code below but it doesn't give me the result I was looking for:
data = [(2,3,4,...),(23,42,54,...),......]
d=[]
for t in data:
d.append(str(t))
This gets close:
data = [[str(x) for x in tup] for tup in data]
If you actually need tuples:
data = [tuple(str(x) for x in tup) for tup in data]
Or, if you prefer a more "functional" approach:
data = [tuple(map(str, tup)) for tup in data]
Though it seems that map has fallen out of favor with the python crowd (or maybe it never was actually in favor ;-).
This will recursively convert infinitely nested lists and tuples:
def stringify(something):
if type(something) == list:
return [stringify(x) for x in something]
elif type(something) == tuple:
return tuple(stringify(list(something)))
else:
return str(something)
Related
I have a list of tuples like this:
tuple_list = [(['MATH120'], 3.665, 0.4737615433949868), (['GER'], 3.4566666666666666, 0.3967146329542181), (['FREE'], 3.415636363636364, 0.450256863026264), ([''], 0.041607963246554365, 0.38832820111766464)]
and what I want to do is convert this to:
result = [['MATH120', 3.665, 0.4737615433949868],['GER', 3.4566666666666666, 0.3967146329542181],['FREE', 3.415636363636364, 0.450256863026264]]
meaning that I want to convert it into a list of 3 pairs and delete the whole tuple if the list it has inside has only elements that are empty and delete also the empty strings that might exist in the tuple for example if it was like this:
tuple_list = [(['MATH120',''], 3.665, 0.4737615433949868), (['GER','',''], 3.4566666666666666, 0.3967146329542181), (['FREE'], 3.415636363636364, 0.450256863026264), ([''], 0.041607963246554365, 0.38832820111766464)]
I want it to turn to the same as previous:
result = [['MATH120', 3.665, 0.4737615433949868],['GER', 3.4566666666666666, 0.3967146329542181],['FREE', 3.415636363636364, 0.450256863026264]]
I tried doing this in order to put them just in list:
result= [list(map(list, l)) for l in tuple_list]
but I kept on getting error because of the float values:
TypeError: 'float' object is not iterable
If your data is always regular like that, and you only want the first element in the inner lists, then simply:
>>> [[x, y, z] for [x, *_], y, z in data]
[['MATH120', 3.665, 0.4737615433949868], ['GER', 3.4566666666666666, 0.3967146329542181], ['FREE', 3.415636363636364, 0.450256863026264], ['', 0.041607963246554365, 0.38832820111766464]]
FINAL EDIT:
Since you've clarified that they are empty strings, we can do something a little nicer:
>>> [ [*filter(None, lst), a, b] for lst, a, b in data if any(lst) ]
[['MATH120', 3.665, 0.4737615433949868], ['GER', 3.4566666666666666, 0.3967146329542181], ['FREE', 3.415636363636364, 0.450256863026264]]
>>>
Which I actually think is quite nicely declarative
result= [ [e for e in l if e] + list(t) for l, *t in tuple_list if any(l) ]
[e in t[0] if e] removes empty strings from a sublist; then the remaining elements of the tuple are appended; but if there are no non-empty elements in a list (any(t[0]) is False) then this tuple is skipped.
The reason you get this error is because when you call map(list, l), l refers to an inner tuple (E.G. (['MATH120'], 3.665, 0.4737615433949868)), and those floats cannot be converted to a list directly. I recommend doing something like the following:
for listIndex in range(tuple_list):
tuple_list[listIndex] = list(tuple_list[listIndex]) # Converts inner tuples to list
for element in inner_tuple:
if isinstance(element, list): # checks if element inside tuple is list
#do logic on list that you need
If your first element is always a list in your tuple, just account for it in more hardcoded way. It will only work with data in same format as examples you presented, list(tuple(list(...), ...), ...)
result_list = []
for x in tuple_list:
temp_tuple = []
if (len(x[0]) == 1 and x[0][0] == '') or len(x[0]) == 0:
continue
for y in x[0]:
if y == '':
continue
temp_tuple.append(y)
for y in range(1, len(x)):
temp_tuple.append(x[y])
result_list.append(temp_tuple)
I tested and result on examples and output was like you asked.
This solution is not one-line solution like other answers. But I personally prefer to avoid one-line loops in python if I can. That makes it easier for me to read it.
You just had one level too much. Use this:
result = [list(x) for x in tuple_list]
or
result = list(map(list, tuple_list))
I wanna make
Input:
x: 1,2,3
y: 4,5,6
Output:
xy: [[1,4],[2,5],[3,6]]
using function parse_list(str_x, str_y)
I'm a beginner of programming... Please help me.
def parse_list(str_x, str_y):
list_x = str_x.split(',')
list_y = str_y.split(',')
xy=[]
for i in range(len(list_x)):
xy[i][0]=list_x[i]
xy[i][1]=list_y[i]
str_x = input('x: ')
str_y = input('y: ')
parse_list(str_x, str_y)
It doesn't work, please tell me the better way.
You are probably getting an IndexError, because the list is empty when you are trying to access its element with xy[i][0]=list_x[i]. You should add elements to the list (for example using .append()) before accessing them.
If you want to keep the resulting list with string elements, then this should work:
def parse_list(str_x, str_y):
return list(
zip(str_x.split(','), str_y.split(',')))
If you want to convert all the elements to int, then you could try this instead:
def parse_list(str_x, str_y):
xy = []
for x, y in zip(str_x.split(','), str_y.split(',')):
# careful: this may raise 'ValueError' if its not a valid 'int'
xy.append([int(x), int(y)])
return xy
You can split the strings with commas, map the items to integers, and zip the two lists:
def parse_list(str_x, str_y):
return list(zip(map(int, str_x.split(',')), map(int, str_y.split(','))))
This returns a list of tuples. If you prefer that it returns a list of lists you can map the tuples that zip generates to lists:
def parse_list(str_x, str_y):
return list(map(list, zip(map(int, str_x.split(',')), map(int, str_y.split(',')))))
Assume you have a list such as
x = [('Edgar',), ('Robert',)]
What would be the most efficient way to get to just the strings 'Edgar' and 'Robert'?
Don't really want x[0][0], for example.
Easy solution, and the fastest in most cases.
[item[0] for item in x]
#or
[item for (item,) in x]
Alternatively if you need a functional interface to index access (but slightly slower):
from operator import itemgetter
zero_index = itemgetter(0)
print map(zero_index, x)
Finally, if your sequence is too small to fit in memory, you can do this iteratively. This is much slower on collections but uses only one item's worth of memory.
from itertools import chain
x = [('Edgar',), ('Robert',)]
# list is to materialize the entire sequence.
# Normally you would use this in a for loop with no `list()` call.
print list(chain.from_iterable(x))
But if all you are going to do is iterate anyway, you can also just use tuple unpacking:
for (item,) in x:
myfunc(item)
This is pretty straightforward with a list comprehension:
x = [('Edgar',), ('Robert',)]
y = [s for t in x for s in t]
This does the same thing as list(itertools.chain.from_iterable(x)) and is equivalent in behavior to the following code:
y = []
for t in x:
for s in t:
y.append(s)
I need to send this string to another function.
If your intention is just to call a function for each string in the list, then there's no need to build a new list, just do...
def my_function(s):
# do the thing with 's'
x = [('Edgar',), ('Robert',)]
for (item,) in x:
my_function(item)
...or if you're prepared to sacrifice readability for performance, I suspect it's quickest to do...
def my_function(t):
s = t[0]
# do the thing with 's'
return None
x = [('Edgar',), ('Robert',)]
filter(my_function, x)
Both map() and filter() will do the iteration in C, rather than Python bytecode, but map() will need to build a list of values the same length of the input list, whereas filter() will only build an empty list, as long as my_function() returns a 'falsish' value.
Here is one way:
>>> [name for name, in x]
['Edgar', 'Robert']
Note the placement of the comma, which unpacks the tuple.
>>> from operator import itemgetter
>>> y = map(itemgetter(0), x)
>>> y
['Edgar', 'Robert']
>>> y[0]
'Edgar'
>>> y[1]
'Robert'
I need to be able to find the first common list (which is a list of coordinates in this case) between a variable amount of lists.
i.e. this list
>>> [[[1,2],[3,4],[6,7]],[[3,4],[5,9],[8,3],[4,2]],[[3,4],[9,9]]]
should return
>>> [3,4]
If easier, I can work with a list of all common lists(coordinates) between the lists that contain the coordinates.
I can't use sets or dictionaries because lists are not hashable(i think?).
Correct, list objects are not hashable because they are mutable. tuple objects are hashable (provided that all their elements are hashable). Since your innermost lists are all just integers, that provides a wonderful opportunity to work around the non-hashableness of lists:
>>> lists = [[[1,2],[3,4],[6,7]],[[3,4],[5,9],[8,3],[4,2]],[[3,4],[9,9]]]
>>> sets = [set(tuple(x) for x in y) for y in lists]
>>> set.intersection(*sets)
set([(3, 4)])
Here I give you a set which contains tuples of the coordinates which are present in all the sublists. To get a list of list like you started with:
[list(x) for x in set.intersection(*sets)]
does the trick.
To address the concern by #wim, if you really want a reference to the first element in the intersection (where first is defined by being first in lists[0]), the easiest way is probably like this:
#... Stuff as before
intersection = set.intersection(*sets)
reference_to_first = next( (x for x in lists[0] if tuple(x) in intersection), None )
This will return None if the intersection is empty.
If you are looking for the first child list that is common amongst all parent lists, the following will work.
def first_common(lst):
first = lst[0]
rest = lst[1:]
for x in first:
if all(x in r for r in rest):
return x
Solution with recursive function. :)
This gets first duplicated element.
def get_duplicated_element(array):
global result, checked_elements
checked_elements = []
result = -1
def array_recursive_check(array):
global result, checked_elements
if result != -1: return
for i in array:
if type(i) == list:
if i in checked_elements:
result = i
return
checked_elements.append(i)
array_recursive_check(i)
array_recursive_check(array)
return result
get_duplicated_element([[[1,2],[3,4],[6,7]],[[3,4],[5,9],[8,3],[4,2]],[[3,4],[9,9]]])
[3, 4]
you can achieve this with a list comprehension:
>>> l = [[[1,2],[3,4],[6,7]],[[3,4],[5,9],[8,3],[4,2]],[[3,4],[9,9]]]
>>> lcombined = sum(l, [])
>>> [k[0] for k in [(i,lcombined.count(i)) for i in lcombined] if k[1] > 1][0]
[3, 4]
Basically, I'm trying to flatten a list in my function but ignore that (you can also ignore the print functions I put in).
take x = [[1,2,3],4,5] to be my variable.
I call prob7(x) but the issue is that when type([1,2,3]) gets checked == list, it returns false. Why is that? I explicitly check this on the interpreter command line and it returns true. But inside the function, I get a false.
Just a bug that I missed because I'm sleepy or am I misunderstanding some part of the Python language? I run version 2.6 if it matters.
def prob7(list): # flatten a list
tempList = []
if list: # meaning if there are elements in the list and it is not empty
for i in list:
if type(i) != list:
print tempList,'if',i,type(i)==list
tempList.append(i)
else:
print tempList,'else',i
tempList.extend(prob7(i))
return tempList
Just not use 'list' as a variable name and use isinstance(var, list) instead of type(var) == list.
Please find corrected sample below.
def prob7(mylist): # flatten a list
tempList = []
if mylist: # meaning if there are elements in the list and it is not empty
for i in mylist:
if not isinstance(i, list):
print tempList, 'if', i, isinstance(i, list)
tempList.append(i)
else:
print tempList, 'else', i
tempList.extend(prob7(i))
return tempList
Or if you don't really required to use recursion and you don't care about values order then you can use something like this:
lVals = [[1,2,3],4,5, [1,[4,7]]]
def make_flat(mylist): # flatten a list
while any(isinstance(x, list) for x in mylist):
for i, val in enumerate(mylist):
if isinstance(val, list):
mylist.extend(mylist.pop(i))
break
return mylist
make_flat(lVals)
>>> [4, 5, 1, 2, 3, 1, 4, 7]
Artisom has your answer. In addtion, type checks are not very Pythonic. Duck typing often is the way to go. In case your elements are numbers only, the following does the job too, without explicit type checks but behavior checks:
def prob7(inlist): # flatten a list
outlist = []
for x in inlist:
try:
outlist += x
except TypeError:
outlist.append(x)
return outlist
Note that string elements in this implementation would behave like nested lists. Anyway, just wanted to illustrate what it means to expect behavior, not types.
Some alternate approaches:
# Iterative, but more functional-style
def flatten(a_list):
while any(isinstance(x, list) for x in a_list):
a_list = sum((x if isinstance(x, list) else [x] for x in a_list), [])
return a_list
# Using a generator recursively,
# then evaluating the generator to produce the list
# instead of explicitly appending each element.
def flatten_gen(a_list):
for x in a_list:
if isinstance(x, list):
for y in flatten_gen(x): yield y
else: yield x
def flatten(a_list): return list(flatten_gen(a_list))
The problem here is you are using a local variable name (list) that is the same as the global list type. You should change your variable name. Also, when checking types like that you can use the is operator.
type(l) is list
But here's my version of flatten.
def flatten(alist):
rv = []
for val in alist:
if isinstance(val, list):
rv.extend(flatten(val))
else:
rv.append(val)
return rv
This does not alter the original list, but returns a new list. This is consistent with most other patterns.