Related
I can generate combinations from a list of numbers using itertools.combinations, such as the following:
from itertools import combinations
l = [1, 2, 3, 4, 5]
for i in combinations(l,2):
print(list(i))
This generates the following:
[1, 2]
[1, 3]
[1, 4]
[1, 5]
[2, 3]
[2, 4]
[2, 5]
[3, 4]
[3, 5]
[4, 5]
How can I generate just one of these list pairs at a time and save it to a variable? I want to use each pair of numbers, one pair at a time, and then go to the next pair of numbers. I don't want to generate all of them at once.
The itertools library actually returns a generator for most of it's functions (including itertools.combinations()). You can read more about Generators here. Basically, it's a function that lazily calculates values instead of generating everything all at once.
You can just get a single value out of a generator using the next command. Take a look at the following snippet:
import itertools
l = [1, 2, 3, 4, 5]
comb_generator = itertools.combinations(l, 2)
temp = next(comb_generator) #Get the first combo into a var
print(temp)
#Do some other stuff
temp = next(comb_generator) #Get another combo
print(temp)
Whenever you want a new combination, you can get it by calling next() on your generator.
The general project is to re-build an enigma machine. However, the problem is this:
I have a list and I want to rearrange it in a way that the first element is appended to the same list and then the first element is deleted.
Basicly, I want this:
l = [1, 2, 3, 4]
l_new = [2, 3, 4, 1]
for this purpose I constructed the function
def switch_up(list):
list.append(list[0])
del list[0]
return list
The problem: When calling this function with a list, it does not only return the changed list, but changes the original list given as the argument.
The full code looks like this:
def switch_up(list):
list.append(list[0])
del list[0]
return list
my_list = [1, 2, 3, 4]
my_list2 = switch_up(my_list)
print(my_list)
print(my_list2)
My expected/desired output would be:
[1, 2, 3, 4]
[2, 3, 4, 1]
The output I get is:
[2, 3, 4, 1]
[2, 3, 4, 1]
You are altering the list passed into the function. That isn't a copy of the list it's the same list. You should just make a copy and return it with something like:
def switch_up(l):
# list slices will make shallow copy
return l[1:] + l[:1]
my_list = [1, 2, 3, 4]
my_list2 = switch_up(my_list)
print(my_list)
# [1, 2, 3, 4]
print(my_list2)
# [2, 3, 4, 1]
Lists are mutable in python and therefore it is assumed, that you want to do operations on the original list. If you do not want that you have to manually copy your list for example with list.copy. For more information on copy please see this stackoverflow question
All you created is a "pointer" called my_list2 to the same value as my_list if you would for example iclude my_list2[1] = 'a' the result would be:
my_list = [2, 'a', 4, 1]
my_list2 = [2, 'a', 4, 1]
And btw you should never name your variables the same as inbuilt functions, like list
This question already has answers here:
List on python appending always the same value [duplicate]
(5 answers)
Closed 4 years ago.
I have this code:
lst = []
given = [1, 2, 3, 4, 5]
result = []
for item in given:
lst.append(item)
print(lst)
result.append(lst)
print(result)
My expected result is [[1], [1, 2], [1, 2, 3], ...], but displayed result is [[1, 2, 3, 4, 5], ...] with 12345 repeated 5 times. What is wrong?
lst printed is as expected, which is [1] for the first loop, [1, 2] for the second loop, and so on.
Python doesn't create copy of lst every time when you append it to result, it just inserts reference. As a result you get list with N references to same list.
To create a copy of lst you can use lst.copy(). Also list slice operator works same lst[:].
Shortened version of your code:
given = [1, 2, 3, 4, 5]
result = [given[0 : i + 1] for i in range(len(given))]
print(result)
Result:
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]
The problem is that you are appending the list as such which is equivalent to appending the reference object to the original list. Therefore, whenever the original list is modified, the changes are reflected in the places where the reference is created, in this case in result. As you keep iterating via the for loop, all your references appended in result keep getting updated with the latest value of lst. The final result is that at the end of the for loop, you have appended 5 references to the original list lst and all of them store the latest value of lst being [1,2,3,4,5].
There are several ways to avoid this. What you need is to copy only the values. One of them is to use lst[:]. other way is to use lst.copy()
for item in given:
lst.append(item)
print(lst)
result.append(lst[:])
print (result)
# [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]
List is a mutable data type, there is only one copy in memory for a list unless you explicitly copy it to another variable. So
result.append(lst)
just appends a reference of the real copy and all the refercences point to the same copy.
In conclusion, you should learn about mutable/immutable data types and reference count in python.
Append lst.copy() gives the right output.
lst = []
given = [1,2,3,4,5]
result = []
for item in given:
lst.append(item)
print(lst)
result.append(lst.copy())
print(result)
I want my code's 2nd function to modify the new list made by my 1st function.
If I am understanding things correctly giving a list as an argument will give the original list (my_list in this case).
so the code removes 1 & 5 and then adds 6, but not 7?
my_list = [1, 2, 3, 4, 5]
def add_item_to_list(ordered_list):
# Appends new item to end of list which is the (last item + 1)
ordered_list.append(my_list[-1] + 1)
def remove_items_from_list(ordered_list, items_to_remove):
# Removes all values, found in items_to_remove list, from my_list
for items_to_remove in ordered_list:
ordered_list.remove(items_to_remove)
if __name__ == '__main__':
print(my_list)
add_item_to_list(my_list)
add_item_to_list(my_list)
add_item_to_list(my_list)
print(my_list)
remove_items_from_list(my_list, [1,5,6])
print(my_list)
output of
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6, 7, 8]
[2, 4, 6, 8]
instead of wanted
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6, 7, 8]
[2, 3, 4, 7, 8]
Thank you and sorry for the elementary question
In your remove_items_from_list function you are iterating through the wrong list. You should iterate through every item in the items_to_remove list like this:
def remove_items_from_list(ordered_list, items_to_remove):
# Removes all values, found in items_to_remove list, from my_list
for item in items_to_remove:
ordered_list.remove(item)
This will now iterate through each item in the remove list and remove it from you ordered_list.
There is a bug in the remove_items_from_list function. For it to achieve what you want it should go:
def remove_items_from_list(ordered_list, items_to_remove):
# Removes all values, found in items_to_remove list, from my_list
for item in items_to_remove:
ordered_list.remove(item)
As a side note, your code has incorrect number of blank lines before function definitions. Should be two blank lines before the function, and not more than one blank line inside functions. It seems not to have affected the code for now, but makes it harder to read, and could cause problems in future.
In the second function you want to iterate over items_to_remove (and not your original list) and then remove every item.
Use:
def remove_items_from_list(ordered_list, items_to_remove):
for item_to_remove in items_to_remove:
ordered_list.remove(item_to_remove)
And don't change the a list when you are iterating over it,which may cause bug.
I am trying to figure out how to append multiple values to a list in Python. I know there are few methods to do so, such as manually input the values, or put the append operation in a for loop, or the append and extend functions.
However, I wonder if there is a more neat way to do so? Maybe a certain package or function?
You can use the sequence method list.extend to extend the list by multiple values from any kind of iterable, being it another list or any other thing that provides a sequence of values.
>>> lst = [1, 2]
>>> lst.append(3)
>>> lst.append(4)
>>> lst
[1, 2, 3, 4]
>>> lst.extend([5, 6, 7])
>>> lst.extend((8, 9, 10))
>>> lst
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> lst.extend(range(11, 14))
>>> lst
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
So you can use list.append() to append a single value, and list.extend() to append multiple values.
Other than the append function, if by "multiple values" you mean another list, you can simply concatenate them like so.
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> a + b
[1, 2, 3, 4, 5, 6]
If you take a look at the official docs, you'll see right below append, extend. That's what your looking for.
There's also itertools.chain if you are more interested in efficient iteration than ending up with a fully populated data structure.
if the number of items was saved in a variable say n. you can use list comprehension and plus sign for list expansion.
lst = ['A', 'B']
n = 1
new_lst = lst + ['flag'+str(x) for x in range(n)]
print(my_lst)
>>> ['A','B','flag0','flag1']
One way you can work around this type of problem is -
Here we are inserting a list to the existing list by creating a variable new_values.
Note that we are inserting the values in the second index, i.e. a[2]
a = [1, 2, 7, 8]
new_values = [3, 4, 5, 6]
a.insert(2, new_values)
print(a)
But here insert() method will append the values as a list.
So here goes another way of doing the same thing, but this time, we'll actually insert the values in between the items.
a = [1, 2, 7, 8]
a[2:2] = [3,4,5,6]
print(a)