This question already has answers here:
Iterating over every two elements in a list [duplicate]
(22 answers)
Closed 4 years ago.
I am looking for a nice pythonian solution to read two elements out of a list in Python 3. What do I need to write for ??? in the following code:
it = [1,2,3,4,5,6]
for x, y in ??? :
print (x, y)
The desired output would be:
1 2
3 4
5 6
Also one could solve it with indexed for-loop. But this is also ugly (IMHO)
Use zip(*[iter(it)] * 2), as seen in this answer.
it = [1,2,3,4,5,6]
for x, y in zip(*[iter(it)] * 2):
print(x, y)
Another easy way without zip is:
i = 0
while i < len(it)-1:
print(it[i], it[i+1])
i += 2
Another cheap option, using indices. You might not like them, but they are fast.
it = [1,2,3,4,5,6]
for x in range(0, len(it)-1, 2):
print(it[x], it[x+1])
Here is another approach which will work in Python3:
def pair(a):
# Or simply:
# return zip(a[::2], a[1::2])
for k, v in zip(a[::2], a[1::2]):
yield k, v
a = [1,2,3,4,5,6]
final = list(pair(a))
print(final)
Output:
[(1, 2), (3, 4), (5, 6)]
Got this to work for your case:
l = [1,2,3,4,5,6]
print(*[' '.join([str(a) for a in x]) for x in zip(l[::2],l[1:][::2])],sep='\n')
First I had to use l[::2] to create a list the odd numbers in the list, then l[1:][::2] to get even numbers. Did this using slicing function which is quite useful link
Then I zipped them together to match 1st, 2nd, 3rd elements etc link
Then I used list comprehension to create a list of each of those sets. The problem is that they were sets and not text as above. To resolve this I changed my sets to string str() .
Now that the individual sets have been turned into string, you can join with ' '.
You still have a set of 3 but you can print each line with print(*[list here],sep='\n') link
Learned a few new tricks, hope this helps!
Related
This question already has answers here:
Slicing out a specific from a list
(2 answers)
Index all *except* one item in python
(11 answers)
Closed 2 years ago.
Is it possible to use slice but on a specific element on a list? For example a = [1,2,3,4,5,6,7,8,9] I want to make a for loop that prints out the whole list except the second element.
I want to make something like this:
for i in a[something_slice]:
print(i)
Is this possible?
For excluding just one element, the 2 slice lst[:i] + lst[i + 1:] approach proposed by #Applet123 is probably the fastest (Or perhaps a excluded = lst.pop(1) to extract the excluded element and for x in lst: print(x) for printing all the others; then lst.insert(1,excluded) to put the excluded element back on the list. See data structures docs for details).
If you just want to filter out certain indexes, instead of a for loop I recommend you use a more pythonic (and intuitive) approach based on list comprehensions and enumerate:
myList = [1,2,3,4,5,6,7,8,9]
excludedIndices = [1]
myFilteredList = [x for i, x in enumerate(myList) if i not in excludedIndices]
print (myFilteredList)
# output:
# [1,3,4,5,6,7,8,9]
# or, to actually print each element individually:
for x in myFilteredList:
print (x)
# which can also work as a 2-liner with inline filtering:
for i, x in enumerate(myList):
if i not in excludedIndices: print(x)
Also check out python usage of filter and map builtin functions, which may be overkill for this purpose but still offer a general and more powerful solution for this kind of processing:
# filters an enumerated element
def myFilter(element):
return element[0] not in excludedIndices
# maps an enumerated element to a function
def myMap(element):
print(element[1])
# runs myMap function for each enumerated element on the list filtered by myFilter
for x in map(myMap,filter(myFilter,enumerate(myList))): pass
Which you can also turn into a one-liner using lambda expressions:
for x in map(lambda x: print(x[1]),filter(lambda x: x[0] not in excludedIndices,enumerate(myList))): pass
you can do it without slicing, using enumerate()
index_to_skip=1
for idx,item in enumerate(a):
if idx!=index_to_skip:
print(item)
If you actually want to slice the list, you can use 2 slices to slice around it:
def exclude(lst, i):
return lst[:i] + lst[i + 1:]
exclude([1, 2, 3, 4, 5], 1) # [1, 3, 4, 5]
If you just want to loop through it, you could alternatively just skip when the index reaches the value you want to skip:
for i, v in enumerate(a):
if i == 1:
continue
print(v)
This question already has answers here:
Powersets in Python using itertools
(3 answers)
Closed 3 years ago.
I want to print all permutations of length 1-4 for the following list [1,2,3,4]
I know I could just set up a for-loop and pass in the for-loop index as an argument, but I was trying to get the following code to work:
import itertools
nums = [1,2,3,4]
perms = itertools.permutations(nums,range(1,4))
print(list(perms))
The hope was that the argument range(1,4) would run the intertools.permutations(nums) on string lengths 1, 2, 3 and 4.
Any ideas if it is possible to do this using the itertools notation?
Would it also be possible to print the case for length = 1 as:
(1), (2), (3), (4)
not
(1,), (2,), (3,), (4,)
Chain together 4 calls of permutations:
from itertools import chain, permutations
nums = [1,2,3,4]
perms = list(chain.from_iterable(permutations(nums, i) for i in range(1,5)))
print(perms)
If you want to print the 1-tuples as individual values, you'll need to handle that separately:
for t in perms:
if len(t) == 1:
print("(t[0])")
else:
print(t)
That's if you are concerned about the appearance of the tuple. If you truly want a non-tuple value, you'll need to extract the value separately, and keep in mind that 1 and (1) are the exact same value.
perms = list(nums, # permutations(nums, 1) == nums
chain.from_iterable(permutations(nums, i) for i in range(2,5)))
You can also write it as a generator expression:
perms = (it for i in range(1, 4) for it in itertools.permutations(nums,i))
This question already has answers here:
Convert string to variable name in python [duplicate]
(3 answers)
Closed 7 years ago.
How can I assign values to variables by using two lists:
Numbers =[1,2,3,4,]
Element= ["ElementA","ElementB","ElementC","ElementD"]
for e, n in zip(Element, Numbers):
e+ ' = ' +n #this part is wrong
What i want is a result like this in the end:
print ElementA
>1
print ElementB
>2
print ElementC
>3
print ElementD
>4
So what im trying to do is to fill up variables created from one list (Element) with values from another list (Numbers) in a kind of loop style.
Does anyone know how to archive something like that?
It should also be possible to assign many values contained in a list/array to variables.
Do not do that.
You're already working with lists, so just create a list instead of hacking some hard-coded names. You could use a dictionary if you really wanted to use identifiers like A, B, etc., but you'd have a problem with more than 26 items, and you're just using it to make a sequence anyway. Integers are great for that, and of course we'll start at 0 because that's how it works.
>>> numbers = [1, 2, 3, 4]
>>> elements = [item for item in numbers]
>>> elements[0]
1
And at this point we can see that, for this example at least, you already had what you were looking for this whole time, in numbers.
>>> numbers = [1, 2, 3, 4]
>>> numbers[0]
1
Perfect.
You may use exec but this is generally the wrong way to go.
for e, n in zip(Element, Numbers):
exec(e + ' = ' + n)
You better should use a dictionnary:
my_dict = {}
for e, n in zip(Element, Numbers):
my_dict[e] = n
Even simpler:
my_dict = dict(zip(Element, Numbers))
This question already has answers here:
How to extract the n-th elements from a list of tuples
(8 answers)
Closed 8 years ago.
I want to write a succinct and elegant code for the following problem:
Assuming that I have a list of tuples:
[(x1,y1), (x2,y2), ....., (xn,yn)].
I want to create a list [y1, y2, ....,yn] without using the loops.
Any help appreciated.
You can do this:
>>> x = [(1,2),(3,4),(5,6)]
>>> x2 = [k[1] for k in x]
>>> x2
[2, 4, 6]
The list comprehension does a loop internally, but you didn't have to type the words for or while. Is that what you're looking for?
You could use zip to transpose the sequence from "N tuples each of size 2" to "2 tuples each of size N", and then slice off everything but the second result:
seq = [("z", "a"), ("y", "b"), ("x", "c")]
print zip(*seq)[1]
Result:
('a', 'b', 'c')
mtrw has the right idea in standard Python. However, if you'd like to make the jump directly to numpy, I highly recommend it. It allows for all sort of indexing:
import numpy as np
x = np.array([(1,2),(3,4),(4,5)])
x[:,1]
Result:
array([2,4,6])
Edit:
In addition to this simple indexing, you can loop over the arrays like any list, and has all the same properties plus more.
Edit 2: vanilla -> standard
Sorry I'm fairly new to python, but I needed to take 6 individual lists and concatenate them such that they resemble a list of lists.
i.e. a1 from list A + b1 from list B + c1 from list C
and a2 from list A + b2.... etc
should become [[a1,b1,c1], [a2,b2,c2]...]
I tried this:
combList = [[0]*6]*len(lengthList)
for i in range(len(lengthList)):
print i
combList[i][0] = posList[i]
combList[i][1] = widthList[i]
combList[i][2] = heightList[i]
combList[i][3] = areaList[i]
combList[i][4] = perimList[i]
combList[i][5] = lengthList[i]
# i++
print combList
and then tried a variation where I appended instead:
for i in range(len(lengthList)):
print i
combList[i][0].append(posList[i])
combList[i][1].append(widthList[i])
combList[i][2].append(heightList[i])
combList[i][3].append(areaList[i])
combList[i][4].append(perimList[i])
combList[i][5].append(lengthList[i])
# i++
print combList
So I have two questions.
Why didn't either of those work, cus in my mind they should have. And I don't need to put i++ at the bottom right? For some reason it just wasn't working so I was just trouble shooting.
I ended up finding a solution, which is below, but I'd just like to understand what happened in the above two codes that failed so terribly.
for j in range(len(fNameList)):
rows = [fNameList[j], widthList[j], heightList[j], areaList[j], perimeterList[j], lengthList[j]]
print rows
combList.append(rows)
print combList
The issue with at you did is that you are creating a list of 6 references to the same thing.
[0]*6 will generate a list of 6 references to the same number (zero), and [[0]*6]*len(lengthList) will generate a list of references to the same [0]*6 list.
I think the function you want is zip:
A = ['a1','a2','a3']
B = ['b1','b2','b3']
C = ['c1','c2','c3']
print [x for x in zip(A,B,C)]
which gives:
[('a1', 'b1', 'c1'), ('a2', 'b2', 'c2'), ('a3', 'b3', 'c3')]
So in your case, this would work:
combList = [x for x in zip(fNameList, widthList, heightList, areaList, perimeterList, lengthList)]
a = [0]*6 defines a list with 6 references, all those references point to the number 0
[a]*m defines a list with m references, all pointing to a, in this case [0]*6.
The code in your final example works because it adds references to new objects, rather than modifying an existing one repeatedly.
Other people recommended you use zip, and it is indeed the best solution, IMHO.
You are making a list of names all pointing at the same list of six zeros when you do:
combList = [[0]*6]*len(lengthList)
This is equivalent to doing this:
internal_list = [0] * 6
combList = [internal_list, internal_list, internal_list, internal_list, internal_list]
Instead, if you use zip you can get what you want in one pass:
zipped_list = zip(posList, widthList, heightList, areaList, perimList, lengthList)
You could do this with a comprehension across a zip, if the lists are all the same length
[list(tup) for tup in zip (l1, l2, l3...)]
Depending on version of Python and how big your 3 lists are you should use either zip or izip.
izip if you're running Python < 3 (you can use zip as well but if the lists are really big then a generator would be a whole heap faster and better for you).
zip if you're running Python >= 3
from itertools import izip
zipped_list = izip(a,b,c)
for item in zipped_list:
print item
>> (1, 1, 1)
>> (2, 2, 2)
>> (3, 3, 3)
>> (4, 4, 4)
>> (5, 5, 5)
And just for a bit tutoring on how to write good clean looking Python:
Your loop that you've done for i in range(len(lengthList) could very easily be transformed to whats really Pythonic.
for item in lengthList:
Now you're thinking "what about my index, i can't access the index of the element".
Well Python has a fix for that too it's called enumerate and you use it like so:
for index, item in enumerate(lengthlist):
So translating your code down to a more Pythonic syntax:
for index, element in enumerate(lengthList):
combList[index][0].append(posList[index])
combList[index][1].append(widthList[index])
combList[index][2].append(heightList[index])
combList[index][3].append(areaList[index])
combList[index][4].append(perimList[index])
combList[index][5].append(lengthList[index])