Why does list in program give an unexpected output? - python

I am having a problem with my list in python.
I am printing out the list (working), a number that shows the line number (working) and an item in the list that should change every time the list is printed(not working?)
a = ["A", "B", "C", "D", "E"]
b = 0
for x in a:
while b <= 10:
print(a, x, b)
b += 1
My current program output is
['A', 'B', 'C', 'D', 'E'] A 0
['A', 'B', 'C', 'D', 'E'] A 1
['A', 'B', 'C', 'D', 'E'] A 2
['A', 'B', 'C', 'D', 'E'] A 3
so on
the output I would like
['A', 'B', 'C', 'D', 'E'] A 0
['A', 'B', 'C', 'D', 'E'] B 1
['A', 'B', 'C', 'D', 'E'] C 2
['A', 'B', 'C', 'D', 'E'] D 3
and so on
Although, when I try a different program it works perfectly?
list = ["a", "b", "c"]
for a in list:
print(a)
Why does this happen and how can I fix it?

That is because you have the while loop inside the outer for loop (that iterates over the elements of the list. So the inner while loop only exists when b becomes greater than 10, and till then the value of x is A.
For what you want I would suggest using itertools.cycle(). Example -
>>> a = ["A", "B", "C", "D", "E"]
>>>
>>> b = 0
>>> import itertools
>>> acycle = itertools.cycle(a)
>>> for i in range(11):
... print(a,next(acycle),i)
...
['A', 'B', 'C', 'D', 'E'] A 0
['A', 'B', 'C', 'D', 'E'] B 1
['A', 'B', 'C', 'D', 'E'] C 2
['A', 'B', 'C', 'D', 'E'] D 3
['A', 'B', 'C', 'D', 'E'] E 4
['A', 'B', 'C', 'D', 'E'] A 5
['A', 'B', 'C', 'D', 'E'] B 6
['A', 'B', 'C', 'D', 'E'] C 7
['A', 'B', 'C', 'D', 'E'] D 8
['A', 'B', 'C', 'D', 'E'] E 9
['A', 'B', 'C', 'D', 'E'] A 10

You have a double loop here (while inside for) and you never reset the b to 0. To get the result you expected, you should use enumerate:
for idx, x in enumerate(a):
print(a, x, idx)

Related

Is it possible to add lists inside a list?

I created 2 lists in python `
ls = []
a = ['a','b','c','d','e','f']
i = 0
while i < 5:
x = a[-1]
a.pop(-1)
a.insert(0, x)
ls.insert(0, a)
i += 1
print(ls)
What I want to do is to add something from the list filled with letters into an empty list and making the result look like this
ls = [
['a','b','c','d','e','f'],
['f','a','b','c','d','e'],
['e','f','a','b','c','d'],
['d','e','f','a','b','c'],
['c','d','e','f','a','b'],
['b','c','d','e','f','a']
]
I would like to know where I made a mistake in python and the solution.
The list is a mutable object in python, so when you insert the list a in the ls, you are just adding a reference to the list a, instead of adding the whole value.
A workaround would be to insert a copy of a in the ls. One way to create a new copy of the list is using the list() on the list or you can use copy function from copy module. So doing ls.insert(0, a.copy()) would give the same result as below -
ls = []
a = ['a','b','c','d','e','f']
i = 0
while i < 5:
x = a[-1]
a.pop(-1)
a.insert(0, x)
ls.insert(0, list(a)) # updated this
i += 1
print(ls)
Output:
[['b', 'c', 'd', 'e', 'f', 'a'], ['c', 'd', 'e', 'f', 'a', 'b'], ['d', 'e', 'f', 'a', 'b', 'c'], ['e', 'f', 'a', 'b', 'c', 'd'], ['f', 'a', 'b', 'c', 'd', 'e']]
Another easy way to get your expected output would be to -
ls = []
a = ['a','b','c','d','e','f']
for i in range(6):
ls.append(a.copy())
a = [a[-1]] + a[:-1]
print(ls)
Output :
[['a', 'b', 'c', 'd', 'e', 'f'], ['f', 'a', 'b', 'c', 'd', 'e'], ['e', 'f', 'a', 'b', 'c', 'd'], ['d', 'e', 'f', 'a', 'b', 'c'], ['c', 'd', 'e', 'f', 'a', 'b'], ['b', 'c', 'd', 'e', 'f', 'a']]

how do I input custom arrays into rows & columns in 2d character array

Rows = int(input("give the number of rows:"))
Columns = int(input("Give the number of columns:"))
matrix = []
for i in range(Rows):
matrix.append(['a', 'b', 'c','d', 'e'])
for vector in matrix:
print(matrix)
here's the output:
give the number of rows:3
Give the number of columns:3
[['a', 'b', 'c', 'd', 'e']]
[['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']]
[['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']]
[['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']]
[['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']]
[['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']]
[it needed to be like this when the user input the rows and columns 3x3]
a b c
d e f
g h i
There are many ways to initalize an array with a specific size. Below is one of the more concise ways.
Rows = int(input("Give the number of rows:"))
Columns = int(input("Give the number of columns:"))
matrix = [["a"]*Rows]*Columns
print(matrix)
This will give the output
Give the number of rows:3
Give the number of columns:3
[['a', 'a', 'a'], ['a', 'a', 'a'], ['a', 'a', 'a']]
This gives the array sizing that you are looking for.

Group items if trailed by string [duplicate]

I have a list called list_of_strings that looks like this:
['a', 'b', 'c', 'a', 'd', 'c', 'e']
I want to split this list by a value (in this case c). I also want to keep c in the resulting split.
So the expected result is:
[['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]]
Any easy way to do this?
You can use more_itertoools+ to accomplish this simply and clearly:
from more_itertools import split_after
lst = ["a", "b", "c", "a", "d", "c", "e"]
list(split_after(lst, lambda x: x == "c"))
# [['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
Another example, here we split words by simply changing the predicate:
lst = ["ant", "bat", "cat", "asp", "dog", "carp", "eel"]
list(split_after(lst, lambda x: x.startswith("c")))
# [['ant', 'bat', 'cat'], ['asp', 'dog', 'carp'], ['eel']]
+ A third-party library that implements itertools recipes and more. > pip install more_itertools
stuff = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
You can find out the indices with 'c' like this, and add 1 because you'll be splitting after it, not at its index:
indices = [i + 1 for i, x in enumerate(stuff) if x == 'c']
Then extract slices like this:
split_stuff = [stuff[i:j] for i, j in zip([0] + indices, indices + [None])]
The zip gives you a list of tuples analogous to (indices[i], indices[i + 1]), with the concatenated [0] allowing you to extract the first part and [None] extracting the last slice (stuff[i:])
You could try something like the following:
list_of_strings = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
output = [[]]
for x in list_of_strings:
output[-1].append(x)
if x == 'c':
output.append([])
Though it should be noted that this will append an empty list to your output if your input's last element is 'c'
def spliter(value, array):
res = []
while value in array:
index = array.index(value)
res.append(array[:index + 1])
array = array[index + 1:]
if array:
# Append last elements
res.append(array)
return res
a = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
print(spliter('b',a))
# [['a', 'b'], ['c', 'a', 'd', 'c', 'e']]
print(spliter('c',a))
# [['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
What about this. It should only iterate over the input once and some of that is in the index method, which is executed as native code.
def splitkeep(v, c):
curr = 0
try:
nex = v.index(c)
while True:
yield v[curr: (nex + 1)]
curr = nex + 1
nex += v[curr:].index(c) + 1
except ValueError:
if v[curr:]: yield v[curr:]
print(list(splitkeep( ['a', 'b', 'c', 'a', 'd', 'c', 'e'], 'c')))
result
[['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
I wasn't sure if you wanted to keep an empty list at the end of the result if the final value was the value you were splitting on. I made an assumption you wouldn't, so I put a condition in excluding the final value if it's empty.
This has the result that the input [] results in only [] when arguably it might result in [[]].
How about this rather playful script:
a = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
b = ''.join(a).split('c') # ['ab', 'ad', 'e']
c = [x + 'c' if i < len(b)-1 else x for i, x in enumerate(b)] # ['abc', 'adc', 'e']
d = [list(x) for x in c if x]
print(d) # [['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
It can also handle beginnings and endings with a "c"
a = ['c', 'a', 'b', 'c', 'a', 'd', 'c', 'e', 'c']
d -> [['c'], ['a', 'b', 'c'], ['a', 'd', 'c'], ['e', 'c']]
list_of_strings = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
value = 'c'
new_list = []
temp_list = []
for item in list_of_strings:
if item is value:
temp_list.append(item)
new_list.append(temp_list[:])
temp_list.clear()
else:
temp_list.append(item)
if (temp_list):
new_list.append(temp_list)
print(new_list)
You can try using below snippet. Use more_itertools
>>> l = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
>>> from more_itertools import sliced
>>> list(sliced(l,l.index('c')+1))
Output is:
[['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]

How do I make independent lists within in a list?

seats = 4 # user can choose an even input, I put 4 for this example
rows = 4 # user can choose an even or odd input, I put 4 for this example
seats_in_row_list = [i for i in string.ascii_uppercase[:seats]]
main_seat_list = [seats_in_row_list for i in range(rows)]
The output is:
[['A', 'B', 'C', 'D'], ['A', 'B', 'C', 'D'], ['A', 'B', 'C', 'D'], ['A', 'B', 'C', 'D']]
But when I try to change 'A' to 'X' in the first list all of the lists change:
[['X', 'B', 'C', 'D'], ['X', 'B', 'C', 'D'], ['X', 'B', 'C', 'D'], ['X', 'B', 'C', 'D']]
What I'm looking for is this output:
[['X', 'B', 'C', 'D'], ['A', 'B', 'C', 'D'], ['A', 'B', 'C', 'D'], ['A', 'B', 'C', 'D']]
Use copy method to have a copy of the individual list before assigning
main_seat_list = [seats_in_row_list.copy() for i in range(rows)]
If you aren't using seats_in_row_list for anything other than the construction of main_seat_list, you should just inline the definition. Calling list here would be simpler than using a list comprehension.
seats = 4
rows = 4
main_seat_list = [list(string.ascii_uppercase[:seats]) for i in range(rows)]

Split List By Value and Keep Separators

I have a list called list_of_strings that looks like this:
['a', 'b', 'c', 'a', 'd', 'c', 'e']
I want to split this list by a value (in this case c). I also want to keep c in the resulting split.
So the expected result is:
[['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]]
Any easy way to do this?
You can use more_itertoools+ to accomplish this simply and clearly:
from more_itertools import split_after
lst = ["a", "b", "c", "a", "d", "c", "e"]
list(split_after(lst, lambda x: x == "c"))
# [['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
Another example, here we split words by simply changing the predicate:
lst = ["ant", "bat", "cat", "asp", "dog", "carp", "eel"]
list(split_after(lst, lambda x: x.startswith("c")))
# [['ant', 'bat', 'cat'], ['asp', 'dog', 'carp'], ['eel']]
+ A third-party library that implements itertools recipes and more. > pip install more_itertools
stuff = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
You can find out the indices with 'c' like this, and add 1 because you'll be splitting after it, not at its index:
indices = [i + 1 for i, x in enumerate(stuff) if x == 'c']
Then extract slices like this:
split_stuff = [stuff[i:j] for i, j in zip([0] + indices, indices + [None])]
The zip gives you a list of tuples analogous to (indices[i], indices[i + 1]), with the concatenated [0] allowing you to extract the first part and [None] extracting the last slice (stuff[i:])
You could try something like the following:
list_of_strings = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
output = [[]]
for x in list_of_strings:
output[-1].append(x)
if x == 'c':
output.append([])
Though it should be noted that this will append an empty list to your output if your input's last element is 'c'
def spliter(value, array):
res = []
while value in array:
index = array.index(value)
res.append(array[:index + 1])
array = array[index + 1:]
if array:
# Append last elements
res.append(array)
return res
a = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
print(spliter('b',a))
# [['a', 'b'], ['c', 'a', 'd', 'c', 'e']]
print(spliter('c',a))
# [['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
What about this. It should only iterate over the input once and some of that is in the index method, which is executed as native code.
def splitkeep(v, c):
curr = 0
try:
nex = v.index(c)
while True:
yield v[curr: (nex + 1)]
curr = nex + 1
nex += v[curr:].index(c) + 1
except ValueError:
if v[curr:]: yield v[curr:]
print(list(splitkeep( ['a', 'b', 'c', 'a', 'd', 'c', 'e'], 'c')))
result
[['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
I wasn't sure if you wanted to keep an empty list at the end of the result if the final value was the value you were splitting on. I made an assumption you wouldn't, so I put a condition in excluding the final value if it's empty.
This has the result that the input [] results in only [] when arguably it might result in [[]].
How about this rather playful script:
a = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
b = ''.join(a).split('c') # ['ab', 'ad', 'e']
c = [x + 'c' if i < len(b)-1 else x for i, x in enumerate(b)] # ['abc', 'adc', 'e']
d = [list(x) for x in c if x]
print(d) # [['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
It can also handle beginnings and endings with a "c"
a = ['c', 'a', 'b', 'c', 'a', 'd', 'c', 'e', 'c']
d -> [['c'], ['a', 'b', 'c'], ['a', 'd', 'c'], ['e', 'c']]
list_of_strings = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
value = 'c'
new_list = []
temp_list = []
for item in list_of_strings:
if item is value:
temp_list.append(item)
new_list.append(temp_list[:])
temp_list.clear()
else:
temp_list.append(item)
if (temp_list):
new_list.append(temp_list)
print(new_list)
You can try using below snippet. Use more_itertools
>>> l = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
>>> from more_itertools import sliced
>>> list(sliced(l,l.index('c')+1))
Output is:
[['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]

Categories