I need to use set(myList) but it's not possible because I have a list of lists. (It gives a not hashable error).
So I decided to convert each element in the list to a tuple. The list is more or less like this:
MyList[elem1, elem2, [nested1, nested2, [veryNested1, veryNested2]]]
How can I quickly convert everything to a tuple and then back to a list?
Use recursion
MyList = ['elem1', 'elem2', ['nested1', 'nested2', ['veryNested1', 'veryNested2']]]
print MyList
def tupconv(lst):
tuplst = []
for x in lst:
if isinstance(x, list):
tuplst.append(tupconv(x))
else:
tuplst.append(x)
return tuple(tuplst)
def listconv(tup):
lst = []
for x in tup:
if isinstance(x, tuple):
lst.append(listconv(x))
else:
lst.append(x)
return lst
mytup = tupconv(MyList)
print mytup
mylist = listconv(mytup)
print mylist
This should do it:
def lol_to_tuple(lol):
return tuple(el if type(el) is not list
else lol_to_tuple(el)
for el in lol)
To go back, just replace tuple with list:
def tuples_to_lol(tuples):
return list(el if type(el) is not tuple
else tuples_to_lol(el)
for el in tuples)
Hmm, I've seen this kind of problem before. I solved it by using recursion (on the assumption that the final element is the next level, and that I knew how deep the recursion needed to go to split it up.
Having said that, I think it might be better to ask if you were given the list in that format or if you made it like that through some process? That might help us avoid some unnecessary head-bashing.
You can flatten your list with:
In [1]: from compiler.ast import flatten
In [2]: flatten([1, 2, [11, 12, [21, 22]]])
Out[2]: [1, 2, 11, 12, 21, 22]
And then use set(myList)
Related
Not allowed to use any import.
Input:
[frozenset({1}), frozenset({32}), frozenset({40}), frozenset(), frozenset({76})]
Desired Output:
[1,32,40,76]
I'm looking for a concise way. I know how to unpack it with a muli-line for loop.
You can use a list comprehension to generate the output. In order to extract the value in each frozenset, you can create an iterator on it and use the next() method of the iterator to get the first and unique value, if it is not empty:
lst = [frozenset({1}), frozenset({32}), frozenset({40}), frozenset(), frozenset({76})]
out = [next(iter(fset)) for fset in lst if fset]
print(out)
# [1, 32, 40, 76]
We can iterate in the list of frozenset, and change their datatype to list
See here
l = [frozenset({1}), frozenset({32}), frozenset({40}), frozenset(), frozenset({76})]
arr = []
for element in l:
new = list(element)
if new != []:
arr.append(new[0])
print(arr)
Hopefully an example could illustrate this better. I am creating a function that will take either a list of names, various lists of names, just a name or multiple names (not in a list) and make one list of them all (without importing... non-native libraries? I am ignorant here but I mean I want to use only what's already available in python).
def make_one_list(entry1, entry2, entry3 ...):
#regardless of what is entered (well.. it has to be list or element)
#extract elements from list and combine with single elements and...
return one_big_list_of_all_elements
>>>make_one_list(['John','Mark'],'Mike',['Kate','Ally'],'Shawn','Marina'...)
['John','Mark','Mike','Kate','Ally','Shawn','Marina',...]
My pseudo-code is not set in stone, obviously. I think, eventually, some input checking might be in order but not very pythonic in nature to do that. I am simply doing this as a personal communication function for my office.
THANKS!!
Like the chain answer but a bit more straightforward at a glance
def make_one_list(*args):
one_list = []
for arg in args:
if isinstance(arg, str):
one_list.append(arg)
else:
one_list.extend(arg)
return one_list
ret = make_one_list(['John','Mark'],'Mike',['Kate','Ally'],'Shawn','Marina')
print(ret)
You can make a good use of *args in python.
Just traverse through the list of arguements and check whether the arguement is a list or not(by checking its type). If it is, just append that arguement to the one_big_list_of_all_elements.
Pretty simple!
Use chain(iter1, iter2, ...), it is a native library. Though you need to handle the strings that are not in lists.
from itertools import chain
data = ['John','Mark'],'Mike',['Kate','Ally'],'Shawn','Marina'
r = chain(*[x if isinstance(x, list) else [x] for x in data])
print(list(r))
Output:
['John', 'Mark', 'Mike', 'Kate', 'Ally', 'Shawn', 'Marina']
final_list = []
def make_one_list(arg_list):
for arg in arg_list:
if isinstance(arg, list):
for item in arg:
final_list.append(item)
else:
final_list.append(arg)
return final_list
Try this
a = []
b = []
def myFun(*argv):
for arg in argv:
a.append(arg)
myList = str(a).replace('[','').replace(']','')
b = [myList]
print(b)
myFun('Hello', 'Welcome', 'to', 'Geeks',['ff','tt'])
OUTPUT >> ["'Hello', 'Welcome', 'to', 'Geeks', 'ff', 'tt'"]
hope it will help
def flatten(x):
if isinstance(x, list):
tmp = []
for i in x:
tmp.extend(flatten(i))
return tmp
else:
return [x]
Test:
print(repr(flatten([[1, 2, 3], 4, [5], [6, [7, 8], 9]])))
print(repr(flatten(1)))
print(repr(flatten([2])))
Output:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1]
[2]
Fast, clean, works for any type of elements and any depth of nested lists.
Note usage of "extend" which avoids creating excessive intermediate results. This makes the function efficient even for large lists.
We can do what you asked for by connecting all lists with (+)
def make_one_list(*args):
result = []
for i in args:
if isinstance(i, list):
result.append(list(i))
else:
result.append(i)
return result
result = make_one_list(['John','Mark'], ['Kate','Ally'], ['Shawn','Marina'], 'Mike')
print(result)
I am attempting to make a function that will return the unique numbers of a list, in list form. For example:
l = [1,2,2,3,4]
My function would return: [1,2,3,4]
I used a set to do this, and my code is as follows:
def unique_list(l):
se = set(l)
lis = [se]
return lis
print(unique_list(t))
And my output is: [set([1, 2, 3, 4, 5, 6, 7, 8])]
I would assume it has something to do with the se = set(l) or lis = [se] part of my code. However, I am learning by myself and am not exactly sure what could be causing this.
You are casting the list incorrectly. Try something like this..
def unique_list(l):
se = set(l)
lis = list(se)
return lis
print(unique_list(t))
l = [5,5,1,2,2,3,4]
def unique_list(l):
se = set(l) # get all the unique elements of list
lis = list(se) # convert set to list
lis.sort(key=l.index) # preserve order of original list
return lis
print(unique_list(l))
list(set(list_)) is fast for returning a list of unordered unique items.
set(list_) is sufficient for a unique collection if a list not critical.
Here are ways to remove replicates from a list_ while preserving order:
import collections as ct
list(ct.OrderedDict.fromkeys(list_))
In Python 3.6+:
list(dict.fromkeys(list_))
See also this SO post by R. Hettinger and this blog on Fastest way to uniquify a list in Python >=3.6
If I execute this code, the following error message occurs:
IndexError: list index out of range python
def reverse_invert(lst):
inverse_list = []
for i in lst:
if isinstance( i, int ):
inverse_list.append(lst[i])
#print(inverse_list)
print(i)
else:
break
return inverse_list
Why is it?
for i in lst:
will iterate the elements of lst.
If you want to iterate indexes, use
for i in range(len(lst)):
If you want both the element and the index, use enumerate:
for i, el in enumerate(lst):
You are iterating the elements of list but trying to use the element as index. You should change your code like this:
def reverse_invert(lst):
inverse_list = []
for i in lst:
if isinstance( i, int ):
inverse_list.append(i) # changed this one.
#print(inverse_list)
print(i)
else:
break
return inverse_list
List comprehension would work fine:
a = [1, 'a', 2, 3]
print [d for d in a[::-1] if isinstance(d, int)]
And if you want to reverse it just tiny change would do:
a = [1, 'a', 2, 3]
print [d for d in a[::-1] if isinstance(d, int)]
Or maybe I missed your point.
Generally it means that you are providing an index for which a list element does not exist.
E.g, if your list was
[1, 3, 5, 7], and you asked for the element at index 10, you would be well out of bounds and receive an error, as only elements 0 through 3 exist.
I know that "".join(list) converts the list to a string, but what if that list contains a nested list? When I try it returns a TypeError due to unexpected list type. I'm guessing it's possible with error handling, but so far my attempts have been fruitless.
You could try something like this:
''.join(''.join(inner) for inner in outer)
That should work, and won't have too much trouble if the outer list contains both Strings and Lists inside of it, ''.join(myString) -> myString.
Well, if the list is nested, simply flatten it beforehand:
>>> import itertools
>>> lst = [['a', 'b'], ['c', 'd']]
>>> ''.join(itertools.chain(*lst))
'abcd'
Also you could try this snippet:
from collections import Iterable
ellipsis = type('',(),{'__str__' : lambda self:'...'})()
def flatten(collection,stack = None):
if not stack: stack = set()
if id(collection) in stack:
yield ellipsis
return
for item in collection:
if isinstance(item,Iterable):
stack.add(id(collection))
for subitem in flatten(item,stack):
yield subitem
stack.remove(id(collection))
else: yield item
x = [1,2,[3,4,[5],[[6]],7]]
x.append(x)
>>> print(', '.join(map(str,flatten(x))))
1, 2, 3, 4, 5, 6, 7, ...