How could you turn:
[[["hi"], ["hello"]]]
into:
[["hi"], ["hello"]]
While also working with [] as an input
You can use pop function to take the first item out of the list.
>>> a = [["hi"]]
>>> a = a.pop(0)
>>> a
['hi']
Or you can also do something like:
>>> a = [["hi"]]
>>> a = a[0]
>>> a
['hi']
As you edited your question:
>>> a = [[["hi"], ["hello"]]]
>>> a = a.pop(0)
>>> a
[['hi'], ['hello']]
If you have an empty list:
a = []
try:a = a.pop(0) #try if it don't raises an error
except:pass #if error is raised, ingnore it
So , according to the code above, if the list is empty , it will not raise any error.
If you want it to be more simpler:
a = []
if len(a) != 0:a = a[0]
print(a)
You can also make a function to make it simple to use with empty or non-empty lists:
def get(list):
return list if len(list) == 0 else list[0]
Testing our function:
>>> get([])
[]
>>> get([["Hi","Bye"]])
['Hi', 'Bye']
You can use a nested list comprehension to flatten it:
list_of_lists = [['hi'],['hello']]
flattened = [val for sublist in list_of_lists for val in sublist]
print(flattened)
This also works if you have multipe sublists in your list.
You can read more about this on python's documentation
Use itertools
import itertools
ip = [["hi"]]
op = list(itertools.chain.from_iterable(ip))
# op ["hi"]
Or a numpy solution using ravel
import numpy as np
ip = [["hi"]]
ip = np.array(ip)
op = list(ip.ravel())
Since you edited your question, you only want n-1 dimensions, you could use np.transpose -
ip = [[["hi"], ["hello"]]]
op = ip.transpose().reshape(2, 1)
You could check if your input is empty[] explicitly before doing any operations on it, that way to avoid errors -
if ip:
# do some operations on ip
Related
I am creating a if condition-based list. I want to create an empty list if the condition is not satisfied.
My code:
ip_list = []
op_list= [ip_list[0] if len(ip_list)>0 else '']
Present output:
op_list = ['']
Expected output:
op_list = []
This can be accomplished more succinctly via slicing:
op_list = ip_list[:1]
If ip_list has at least one element, op_list will be a singleton list with the first element of ip_list. Otherwise, op_list will be an empty list.
>>> a = [1, 2, 3]
>>> b = []
>>> a[:1]
[1]
>>> b[:1]
[]
op_list = [] if ip_list else [ip_list[0]]
You only need the first element if ip_list has any.
Here is one of the easiest solution for that:
[ip_list[0]] if ip_list else []
I want to make one large list for entering into a database with values from 4 different lists. I want it to be like
[[list1[0], list2[0], list3[0], list4[0]], [list1[1], list2[1], list3[1], list4[1]], etc.....]
Another issue is that currently the data is received like this:
[ [ [list1[0], list1[1], [list1[3]]], [[list2[0]]], etc.....]
I've tried looping through each list using indexs and adding them to a new list based on those but it hasn't worked, I'm pretty sure it didn't work because some of the lists are different lengths (they're not meant to be but it's automated data so sometimes there's a mistake).
Anyone know what's the best way to go about this? Thanks.
First list can be constructed using zip function as follows (for 4 lists):
list1 = [1,2,3,4]
list2 = [5,6,7,8]
list3 = [9,10,11,12]
list4 = [13,14,15,16]
res = list(zip(list1,list2,list3,list4))
For arbitrtary number of lists stored in another list u can use *-notation to unpack outer list:
lists = [...]
res = list(zip(*lists))
To construct list of lists for zipping from you data in second issue use flatten concept to it and then zip:
def flatten(l):
res = []
for el in l:
if(isinstance(el, list)):
res += flatten(el)
else:
res.append(el)
return res
auto_data = [...]
res = list(zip(*[flatten(el) for el in auto_data]))
Some clarification at the end:
zip function construct results of the smallest length between all inputs, then you need to extend data in list comprehension in last code string to be one length to not lose some info.
So if I understand correctly, this is your input:
l = [[1.1,1.2,1.3,1.4],[2.1,2.2,2.3,2.4],[3.1,3.2,3.3,3.4],[4.1,4.2,4.3,4.4]]
and you would like to have this output
[[1.1,2.1,3.1,4.1],...]
If so, this could be done by using zip
zip(*l)
Make a for loop which only gives you the counter variable. Use that variable to index the lists. Make a temporary list , fill it up with the values from the other lists. Add that list to the final one. With this you will et the desired structure.
nestedlist = []
for counter in range(0,x):
temporarylist = []
temporarylist.append(firstlist[counter])
temporarylist.append(secondlist[counter])
temporarylist.append(thirdlist[counter])
temporarylist.append(fourthlist[counter])
nestedlist.append(temporarylist)
If all the 4 lists are the same length you can use this code to make it even nicer.
nestedlist = []
for counter in range(0,len(firstlist)): #changed line
temporarylist = []
temporarylist.append(firstlist[counter])
temporarylist.append(secondlist[counter])
temporarylist.append(thirdlist[counter])
temporarylist.append(fourthlist[counter])
nestedlist.append(temporarylist)
This comprehension should work, with a little help from zip:
mylist = [i for i in zip(list1, list2, list3, list4)]
But this assumes all the list are of the same length. If that's not the case (or you're not sure of that), you can "pad" them first, to be of same length.
def padlist(some_list, desired_length, pad_with):
while len(some_list) < desired_length:
some_list.append(pad_with)
return some_list
list_of_lists = [list1, list2, list3, list4]
maxlength = len(max(list_of_lists, key=len))
list_of_lists = [padlist(l, maxlength, 0) for l in list_of_lists]
And now do the above comprehension statement, works well in my testing of it
mylist = [i for i in zip(*list_of_lists)]
If the flatten concept doesn't work, try this out:
import numpy as np
myArray = np.array([[list1[0], list2[0], list3[0], list4[0]], [list1[1], list2[1], list3[1], list4[1]]])
np.hstack(myArray)
Also that one should work:
np.concatenate(myArray, axis=1)
Just for those who will search for the solution of this problem when lists are of the same length:
def flatten(lists):
results = []
for numbers in lists:
for output in numbers:
results.append(output)
return results
print(flatten(n))
list1 = [1,2,3]
def ex(example_list):
for number in example_list:
if(number == 2):
number = 3
ex(list1)
print(list1)
I need to check if there is the number 2 inside of the list1 and if it's inside of it, I want to modify it to 3.
But if I run the command, number would be 3, but list1 would remain [1,2,3] and not [1,3,3]
You can use enumerate() to get the index of the number you need to change:
list1 = [1,2,3]
def ex(example_list):
for idx, number in enumerate(example_list):
if(number == 2):
example_list[idx] = 3
ex(list1)
print(list1)
The variable number is an object with its own reference and not a reference to the item in the list.
The logic for checking and replacing can be done altogether in a list comprehension using a ternary operator since you're not actually using the index:
list2 = [3 if num==2 else num for num in list1]
References:
List comprehensions
Conditional expressions
In order to modify a list item, you need to know which slot it is in. The .index() method of lists can tell you.
list1 = [1,2,3]
i = list1.index(2)
list1[i] = 2
Now what happens if the list does not contain 2? index() will throw an exception, which normally will terminate your program. You can catch that error, however, and do nothing:
list1 = [1,2,3]
try:
i = list1.index(2)
except ValueError:
pass
else: # no error occurred
list1[i] = 2
So... The problem you're having is that, since number contains a basic type (an int), modifying number doesn't modify the reference inside the list. Basically, you need to change the item within the list by using the index of the item to change:
list1 = [1,2,3]
def ex(example_list):
for i, number in enumerate(example_list):
if(number == 2):
example_list[i] = 3 # <-- This is the important part
ex(list1)
print(list1)
Of just using the index (might be clearer):
list1 = [1,2,3]
def ex(example_list):
for i in range(len(example_list)):
if(example_list[i] == 2):
example_list[i] = 3
ex(list1)
print(list1)
l.index(n) will return the index at which n can be found in list l or throw a ValueError if it's not in there.
This is useful if you want to replace the first instance of n with something, as seen below:
>>> l = [1,2,3,4]
>>> # Don't get to try in case this fails!
>>> l[l.index(2)] = 3
>>> l
[1, 3, 3, 4]
If you need to replace all 2's with 3's, just iterate through, adding elements. If the element isn't 2, it's fine. Otherwise, make it 3.
l = [e if e != 2 else 3 for e in l]
Usage:
>>> l = [1,2,3,4]
>>> l = [e if e != 2 else 3 for e in l]
>>> l
[1, 3, 3, 4]
My professor gave me an exercise where I write a function that returns a list without the duplicate to the old list.
This is the code but I don't know how to write the method without using .remove():
def distinct(lst):
lstnew = []
c = range(len(lst))
for i in range(len(lst)):
if i in range(len(lst)) != c:
lstnew += [i]
c += 1
return lstnew
print distinct([1,3,1,2,6])
print distinct([['a','ab','a','ab']])
I forgot to write an important thing, I must preserve order in the output list.
[UPDATE]
After I read the answer of Jai Srivastav I code this:
def distinct(lst):
lstnew = []
for element in lst:
if element not in lstnew:
lstnew = lstnew + [element]
return lstnew
And It works perfectly
def distinct(lst):
dlst = []
for val in lst:
if val not in dlst:
dlst.append(val)
return dlst
Is this considered cheating?
>>> distinct = lambda lst: list(set(lst))
>>> distinct([1,3,1,2,6])
[1, 2, 3, 6]
>>> distinct(['a','ab','a','ab'])
['a', 'ab']
If order isn't important, you can cast it to a set, then back to a list
def distinct(lst):
return list(set(lst))
If you need to eliminate duplicates AND preserve order you can do this:
def distinct(lst):
seen = set()
for item in lst:
if item not in seen:
yield item
seen.add(item)
a = [1,3,1,2,6]
print(list(distinct(a)))
[1,3,2,6]
b = ['a','ab','a','ab']
print(list(distinct(b)))
['a', 'ab']
See a demo here: https://ideone.com/a2khCg
There are Excellent Solutions That I Already Applied. But my professor said us that we don't must use the methods of the list. Has anyone else got any more thoughts?
I have a list that looks like this
lst = ['a','b','43.23','c','9','22']
I would like to remove the elements that cannot be represented as floats and hence I am doing the following (Attempt 1):
for i,j in enumerate(lst):
try:
lst[i]=float(j)
except:
lst.remove(j)
Which leaves the list looking like this
lst = ['b', 43.23, '9', 22.0]
whereas what I need is this
lst = [43.23, 9.0 , 22.0]
And so I'm doing the following:
for i,j in enumerate(lst):
try:
lst[i]=float(j)
except:
pass
lst = [i for i in lst if type(i) != str]
Is there a cleaner way to do this.?
EDIT: Changed the name of example list from 'list' to 'lst' based on the recommendations below.
You can use the following function from this stackoverflow post:
def isfloat(value):
try:
float(value)
return True
except ValueError:
return False
And, then use it in a list comprehension:
>>> l = ['a','b','43.23','c','9','22']
>>> [float(x) for x in l if isfloat(x)]
# [43.23, 9.0, 22.0]
First you shouldn't name your variable list it will shadow the built-in list function/class. You can use a simple function to do this:
>>> lst = ['a','b','43.23','c','9','22']
>>> def is_float(el):
... try:
... return float(el)
... except ValueError:
... pass
...
>>> [i for i in lst if is_float(i)]
['43.23', '9', '22']
>>> [float(i) for i in lst if is_float(i)] # to return a list of floating point number
[43.23, 9.0, 22.0]
The problem with your code is that you are trying to modify your list while iterating. Instead you can make a copy of your list then use the element index to remove their value.
lst = ['a','b','43.23','c','9','22']
lst_copy = lst.copy()
for el in lst:
try:
float(val)
except ValueError:
lst_copy.remove(el)
Of course this is less efficient than the solution using the list comprehension with a predicate because you first need to make a copy of your original list.
You shouldn't manipulate the list you're iterating through (and you shouldn't call it list neither, since you would shadow the built-in list), since that messes up with the indexes.
The reason why 'b' shows up in your output is that during the first iteration, 'a' is not a float, so it gets removed. Thus your list becomes:
['b','43.23','c','9','22']
and b becomes list[0]. However, the next iteration calls list[1] skipping thus 'b'.
To avoid such an issue, you can define a second list and append the suitable values to that:
l1 = ['a','b','43.23','c','9','22']
l2 = []
for item in l1:
try:
l2.append(float(item))
except ValueError: # bare exception statements are bad practice too!
pass
Would be better in considering iterators to efficiently use system memory. Here is my take to the solution.
def func(x):
try:
return float(x)
except ValueError:
pass
filter(lambda x: x, map(func, li))
Borrowing idea from this post : python: restarting a loop, the first attempt can be fixed with a simple while loop
lst = ['a','b','43.23','c','9','22']
temp = 0
while temp<len(lst):
try:
lst[temp] = float(lst[temp])
temp+=1
except ValueError:
lst.remove(lst[temp])
temp = 0
which leaves me with the desired result (by resetting the loop iterator)
lst = [43.23, 9.0 , 22.0]