I have a list of potentially unknown length like so:
list = [[1,2], [3,4,5], [6]]
I have a for loop that prints these items out, but I also want to be able to add an extra new line in between.
1
2
3
4
5
6
I don't want an additional new line after the final item or before the first. I have a for loop that prints out spaces in between the items in the line. However, there are instances where 1 or more indices are empty. In that case, I don't want to add an extra new line. I've managed to figure out if the first or last index is empty and how to deal with that, but not a middle index.
For example the above result should also be obtainable with this:
list = [[1, 2], [], [3, 4, 5], [6]]
I'm not sure what's the best way to determine this.
Use enumerate() like this:
for i, sub in enumerate(mylist):
if i: print() # If you are using Python 2, remove the parentheses
for x in sub:
print(x)
Edit: I misunderstood your question a little bit. Since your second example list had invalid syntax, I assumed that meant just two sublists. The comment by PaulRooney has cleared that up, so you can do this:
should_print = False
for sub in mylist:
if should_print: print()
for x in sub:
print(x)
should_print = bool(sub)
Since you don't want extra space before or after it sounds like str.join will probably be closer to what you want then other answers that print it chunk by chunk, first you need some generator for each chunk formatted on its own:
def parse_list(mylist):
for seq in mylist:
if seq: #is not empty
yield "\n".join(map(str,seq))
#with print function
print(*parse_list(stuff), sep="\n\n")
#old print statement (but still forward compatible)
print ("\n\n".join(parse_list(stuff)))
you could also just use a generator expression if you only need to use this once:
each_block = ("\n".join(map(str,seq)) for seq in stuff if seq)
print("\n\n".join(each_block))
Or you could condense this to a single line but I wouldn't:
print("\n\n".join("\n".join(map(str,seq)) for seq in stuff if seq))
list = [[1,2],[], [3],[5,6,7],[8]]
first = True
for item in list:
if first and item:
first = False
for number in item:
print(number)
else:
if item:
print('')
for number in item:
print(number)
list = [[1, 7, 3], [], [7, 10], None, [2, 3, 4]]
for i, v in enumerate(list):
if v:
if i != 0:
print
for x in v:
print x
When you say an index is "empty" do you mean it contains None?
list1 = [[1,2], None, [3]]
Or it contains an empty list?
list1 = [[1,2], [], [3]]
Either way, I think this would work:
for i,j in enumerate(list1):
if j:
for k in j:
print k
if i+1 < len(list1):
print
Edit: The above assumes that your input is always a list of lists, as your question seems to imply.
Comparing the current index to the length of the list to determine whether we're at the end will fail if the list has one or more empty elements at the end, e.g.:
list3 = [[1,2], [], [3], []]
This will output:
(start)
1
2
3
(end)
Note that there's a line break after the 3, which it sounds like you wouldn't want. You'd need some additional logic to account for that, if it's a possibility.
This should do the trick:
for idx, i in enumerate(l):
if i:
for j in i:
print(j)
if idx < len(l) - 1:
print()
Related
I am trying to remove adjacent duplicates from a list without using list mutations like del or remove. Below is the code I tried:
def remove_dups(L):
L = [x for x in range(0,len(L)) if L[x] != L[x-1]]
return L
print(remove_dups([1,2,2,3,3,3,4,5,1,1,1]))
This outputs:
[1, 3, 6, 7, 8]
Can anyone explain me how this output occurred? I want to understand the flow but I wasn't able to do it even with debugging in VS code.
Input:
[1,2,2,3,3,3,4,5,1,1,1]
Expected output:
[1,2,3,4,5,1]
I'll replace the variables to make this more readable
def remove_dups(L):
L = [x for x in range(0,len(L)) if L[x] != L[x-1]]
becomes:
def remove_dups(lst):
return [index for index in range(len(lst)) if lst[index] != lst[index-1]]
You can see, instead of looping over the items of the list it is instead looping over the indices of the array comparing the value at one index lst[index] to the value at the previous index lst[index-1] and only migrating/copying the value if they don't match
The two main issues are:
the first index it is compared to is -1 which is the last item of the list (compared to the first)
this is actually returning the indices of the non-duplicated items.
To make this work, I'd use the enumerate function which returns the item and it's index as follows:
def remove_dups(lst):
return [item for index, item in enumerate(lst[:-1]) if item != lst[index+1]] + [lst[-1]]
Here what I'm doing is looping through all of the items except for the last one [:-1] and checking if the item matches the next item, only adding it if it doesn't
Finally, because the last value isn't read we append it to the output + [lst[-1]].
This is a job for itertools.groupby:
from itertools import groupby
def remove_dups(L):
return [k for k,g in groupby(L)]
L2 = remove_dups([1,2,2,3,3,3,4,5,1,1,1])
Output: [1, 2, 3, 4, 5, 1]
A = [[[1,2,3],[4]],[[1,4],[2,3]]]
Here I want to find lists in A which sum of all sublists in list not grater than 5.
Which the result should be [[1,4],[2,3]]
I tried a long time to solve this problem in python. But I still can't figure out the right solution, which I stuck at loop out multiple loops. My code as follows, but its obviously wrong, how to correct it?
A = [[[1,2,3],[4]],[[1,4],[2,3]]]
z = []
for l in A:
for list in l:
sum = 0
while sum < 5:
for i in list:
sum+=i
else:
break
else:
z.append(l)
print z
Asking for help~
Simplification of #KindStranger method in a one-liner:
>> [sub for x in A for sub in x if max(sum(sub) for sub in x) <= 5]
[[1, 4], [2, 3]]
A simple solution which you can think of would be like this -
A = [[[1,2,3],[4]],[[1,4],[2,3]]]
r = [] # this will be our result
for list in A: # Iterate through each item in A
f = True # This is a flag we set for a favorable sublist
for item in list: # Here we iterate through each list in the sublist
if sum(item) > 5: # If the sum is greater than 5 in any of them, set flag to false
f = False
if f: # If the flag is set, it means this is a favorable sublist
r.append(list)
print r
But I'm assuming the nesting level would be the same. http://ideone.com/hhr9uq
This should work for your problem:
>>> for alist in A:
... if max(sum(sublist) for sublist in alist) <= 5:
... print(alist)
...
[[1, 4], [2, 3]]
The one with all()
[t for item in A for t in item if all(sum(t)<=5 for t in item)]
I have a list of lists of tuples of integers.
ls = [[(a_1, a_2), (b_1, b_2)], [(c_1, c_2), (d_1, d_2), (e_1, e_2)], ...]
And I need to delete every item of ls that contains a tuple whose second entry is equal to a predetermined integer.
I tried this:
for item in ls:
for tpl in item:
if tpl[1] == m:
ls.remove(item)
But for some reason, this only removes a few of the list items but not all containing a tuple with second entry = m.
Use a list comprehension:
ls = [item for item in ls if all(tuple[1] != m for tuple in item)]
Or use a filter:
ls = filter(lambda item: all(tuple[1] != m for tuple in item),ls)
Code sucks and we need less of it - here's as sparse as it gets.
[l for l in ls if m not in [i[1] for i in l]]
The best way to filter a list in python is to use a list comprehension:
filtered = [item for item in ls if not(contains_m(item))]
And then all you need is a function that can tell if an item contains m, for example:
def contains_m(item):
return any([tpl[1] == m for tpl in item])
Removing an itme from list is not a good idea while iterating though it.
Try that (if where are talking Python here)
ls = [[('a_1', 'a_2'), ('b_1', 'b_2')], [('c_1', 'c_2'), ('d_1', 'd_2'), ('e_1', 'e_2')]]
m='c_2'
print [ x for x in ls if not [ y for y in x if y[1]==m ]]
Python's list iterator is lazy. This means that when you remove an item from the list, it will skip the next item. For example, say you want to remove all ones from the following list:
[1, 1, 2]
Your for loop starts at index 0:
[1, 1, 2]
^
It removes the element and moves on:
[1, 2]
^
This example is just to help illustrate the issue. One simple workaround is to loop backwards using the index:
for ind in range(len(ls)-1, -1, -1):
item = ls[ind]
for tpl in item:
if tpl[1] == m:
del ls[ind]
break # You can end the inner loop immediately in this case
Another way is to make a copy of the list to iterate over, but remove from the original:
for item in ls[:]:
for tpl in item:
if tpl[1] == m:
ls.remove(item)
break
The last approach can be simplified into creating an output list that contains only the elements that you want. This is easiest to do with a list comprehension. See #AlexeySmirnov 's answer for the best way to do that.
I have a list :
N=[[0,3,4], [0,1,2,9,3], [0,3]]
How do i get it so use ths list to get another list with each list item being a number for each positon of the list items in N so that the new list looks like:
newList=[[0,0,0], [3,1,3], [4,2] ,[9], [3]]
so he first item in newList is a sublist that contains the first number in N[0], the first number in N[1], and the first number in N[2]. The next sublist in N will do the same just for the second positions.
Could make use of izip_longest, then filter out the default values, eg:
from itertools import izip_longest
N=[[0,3,4], [0,1,2,9,3], [0,3]]
new_list = [[el for el in items if el is not None] for items in izip_longest(*N)]
# [[0, 0, 0], [3, 1, 3], [4, 2], [9], [3]]
Try the list comprehension
newList= [reduce(lambda x,y: x + [y[i]] if i<len(y) else x, N, [])
for i in range(max(map(len,N)))]
The for just iterates i upto the length of the longest sublist in N, using map with len to construct a temporary list of the lengths of the lists in N to calculate the max length.
The reduce builds up each sublist in the result by picking out the ith element of the corresponding input sublist -- but only if that sublist is long enough.
A weird and inneficient way (but maybe easy to understand would be):
Get maximum length of the lists in N
Iterate all those lists from 0 to that maximum.
If you got an error, that's because your original list (the one that came from N) doesn't have that item
N=[[0,3,4], [0,1,2,9,3], [0,3]]
newList = []
max_items = max([len(lst) for lst in N])
for n_lst in N:
for i in range(max_items):
if len(newList) <= i:
newList.append([])
try:
newList[i].append(n_lst[i])
except IndexError:
pass
print "new List: %s" % newList
Another approach, that maybe makes the code cleaner is initializing newList to a list with 5 items, since the longest list on your matrix N ([0,1,2,9,3]) has 5 elements. That way you know that your result (the newList variable) is going to have 5 lists:
N=[[0,3,4], [0,1,2,9,3], [0,3]]
newList = []
max_items = max([len(lst) for lst in N])
newList=list([] for _ in range(max_items))
for i in range(max_items):
for n_lst in N:
if len(n_lst) > i:
newList[i].append(n_lst[i])
print "new List: %s" % newList
Note that instead of catching an IndexException, you can also check if the len() of the list you're evaluating is > i
EDIT:
Just saw John Clements response (https://stackoverflow.com/a/22901233/289011) which is by far the cleaner.
How about the following:
# original list
N = [[0,3,4], [0,1,2,9,3], [0,3]]
# create a new list of `n` lists (n being the length of the longest sublist in N)
newList = [[] for i in xrange(max([len(l) for l in N]))]
# iterate over each list
# enumerate - use the index to append into correct target list
for l in N:
for i, val in enumerate(l):
newList[i].append(val)
print newList
Yields:
[[0, 0, 0], [3, 1, 3], [4, 2], [9], [3]]
Hope this helps! :)
Here is a solution that does not use list comprehensions, but also does not require a pre-processing step to determine maximum list length.
N = [[0,3,4], [0,1,2,9,3], [0,3]]
newList = []
progress = True
i = 0;
while (progress):
progress = False
sublist = []
for list in N:
if len(list) <= i:
continue
else:
sublist.append(list[i])
progress = True
if not progress:
break
newList.append(sublist)
i = i+1
print(N)
print(newList)
I am iterating over a list and I want to print out the index of the item if it meets a certain condition. How would I do this?
Example:
testlist = [1,2,3,5,3,1,2,1,6]
for item in testlist:
if item == 1:
print position
Hmmm. There was an answer with a list comprehension here, but it's disappeared.
Here:
[i for i,x in enumerate(testlist) if x == 1]
Example:
>>> testlist
[1, 2, 3, 5, 3, 1, 2, 1, 6]
>>> [i for i,x in enumerate(testlist) if x == 1]
[0, 5, 7]
Update:
Okay, you want a generator expression, we'll have a generator expression. Here's the list comprehension again, in a for loop:
>>> for i in [i for i,x in enumerate(testlist) if x == 1]:
... print i
...
0
5
7
Now we'll construct a generator...
>>> (i for i,x in enumerate(testlist) if x == 1)
<generator object at 0x6b508>
>>> for i in (i for i,x in enumerate(testlist) if x == 1):
... print i
...
0
5
7
and niftily enough, we can assign that to a variable, and use it from there...
>>> gen = (i for i,x in enumerate(testlist) if x == 1)
>>> for i in gen: print i
...
0
5
7
And to think I used to write FORTRAN.
What about the following?
print testlist.index(element)
If you are not sure whether the element to look for is actually in the list, you can add a preliminary check, like
if element in testlist:
print testlist.index(element)
or
print(testlist.index(element) if element in testlist else None)
or the "pythonic way", which I don't like so much because code is less clear, but sometimes is more efficient,
try:
print testlist.index(element)
except ValueError:
pass
Use enumerate:
testlist = [1,2,3,5,3,1,2,1,6]
for position, item in enumerate(testlist):
if item == 1:
print position
for i in xrange(len(testlist)):
if testlist[i] == 1:
print i
xrange instead of range as requested (see comments).
Here is another way to do this:
try:
id = testlist.index('1')
print testlist[id]
except ValueError:
print "Not Found"
Try the below:
testlist = [1,2,3,5,3,1,2,1,6]
position=0
for i in testlist:
if i == 1:
print(position)
position=position+1
[x for x in range(len(testlist)) if testlist[x]==1]
If your list got large enough and you only expected to find the value in a sparse number of indices, consider that this code could execute much faster because you don't have to iterate every value in the list.
lookingFor = 1
i = 0
index = 0
try:
while i < len(testlist):
index = testlist.index(lookingFor,i)
i = index + 1
print index
except ValueError: #testlist.index() cannot find lookingFor
pass
If you expect to find the value a lot you should probably just append "index" to a list and print the list at the end to save time per iteration.
I think that it might be useful to use the curselection() method from thte Tkinter library:
from Tkinter import *
listbox.curselection()
This method works on Tkinter listbox widgets, so you'll need to construct one of them instead of a list.
This will return a position like this:
('0',) (although later versions of Tkinter may return a list of ints instead)
Which is for the first position and the number will change according to the item position.
For more information, see this page:
http://effbot.org/tkinterbook/listbox.htm
Greetings.
Why complicate things?
testlist = [1,2,3,5,3,1,2,1,6]
for position, item in enumerate(testlist):
if item == 1:
print position
Just to illustrate complete example along with the input_list which has searies1 (example: input_list[0]) in which you want to do a lookup of series2 (example: input_list[1]) and get indexes of series2 if it exists in series1.
Note: Your certain condition will go in lambda expression if conditions are simple
input_list = [[1,2,3,4,5,6,7],[1,3,7]]
series1 = input_list[0]
series2 = input_list[1]
idx_list = list(map(lambda item: series1.index(item) if item in series1 else None, series2))
print(idx_list)
output:
[0, 2, 6]
l = list(map(int,input().split(",")))
num = int(input())
for i in range(len(l)):
if l[i] == num:
print(i)
Explanation:
Taken a list of integer "l" (separated by commas) in line 1.
Taken a integer "num" in line 2.
Used for loop in line 3 to traverse inside the list and checking if numbers(of the list) meets the given number(num) then it will print the index of the number inside the list.
testlist = [1,2,3,5,3,1,2,1,6]
num = 1
for item in range(len(testlist)):
if testlist[item] == num:
print(item)
testlist = [1,2,3,5,3,1,2,1,6]
for id, value in enumerate(testlist):
if id == 1:
print testlist[id]
I guess that it's exacly what you want. ;-)
'id' will be always the index of the values on the list.