I have two lists (list_1,list_2) and a function which returns two lists (list_1_f, list_2_f) and I would like to add the items of list_1_f to list_1 and the items of list_2_f to list_2:
def lists():
list_1_f = [10,10,10]
list_2_f = [20,20,20]
return list_1_f,list_2_f
list_1, list_2 = [1,1,1], [2,2,2]
The case is that I always have 2 original lists and the extension is going to be done just for another two extra lists. So that at the end I would have two lists with the original items plus the ones got from the function, and the output would be:
list_1 = [1,1,1,10,10,10]
list_2 = [2,2,2,20,20,20]
I have tried the following lines using extend function but none works:
list_1.extend([]), list_2.extend([]) = lists()
list_1.extend(), list_2.extend() = lists()
list_1.extend, list_2.extend = lists()
I could always do the following:
list_1a, list_2a = lists()
list_1.extend(list_1a)
list_2.extend(list_2a)
But I was wondering if it is even possible to make the extension without having to create two intermediate lists.
It is not directly possible, because what must be on the left side of an assignment cannot be a function call. It can only be built from simple variables, data members, subscripts and commas, parentheses or square brackets.
Best that can be done is to use a comprehension or a map on the right side:
list_1, list_2 = map(lambda x: sum(x, []), zip((list_1, list_2), lists()))
(thanks to #meowgoesthedog for that way)
Whether it is better that a clear code using 3 lines is up to the reader. IMHO the only real use case would be inside a lambda which only supports a unique expression
Related
I am trying to put a series of multiplications inside a list, I am using the code below:
listx = []
for i in range (2):
list = [(3*i)]
listx.append(list)
The problem is that this will put the two results inside two separate lists inside a lists, I just wants the floats to be inside the first list.
listx = []
for i in range (2):
listx.append(3*i)
Just use this one. There is no need to create another list for storing the result. You created another list to store the value and appended that list into your listx
You can also use list comprehensions. Basically it's the same with for cycles but it's much shorter and for simpler operations like yours it's easier to read.
listx = [i*3 for i in range(2)]
This should produce a single list with values multiplied by 3 as integers
I have a list of lists in my script:
list = [[1,2]
[4,3]
[6,2]
[1,6]
[9,2]
[6,5]]
I am looking for a solution to sum up the contents of each "sublist" within the list of lists. The desired output would be:
new_list = [3,7,8,7,11,11]
I know about combining ALL of these lists into one which would be:
new_list = [27,20]
But that's not what i'm looking to accomplish.
I need to combine the two values within these "sublists" and have them remain as their own entry in the main list.
I would also greatly appreciate it if it was also explained how you solved the problem rather than just handing me the solution. I'm trying to learn python so even a minor explanation would be greatly appreciated.
Using Python 3.7.4
Thanks, Riftie.
The "manual" solution will be using a for loop.
new_list = []
for sub_list in list:
new_list.append(sum(sub_list))
or as list compherension:
new_list = [sum(sub_list) for sub_list in list]
The for loop iterates through the elements of list. In your case, list is a list of lists. So every element is a list byitself. That means that while iterating, sub_list is a simple list. To get a sum of list I used sum() build-in function. You can of course iterate manually and sum every element:
new_list = []
for sub_list in list:
sum_val = 0
for element in sub_list:
sum_val = sum_val + element
new_list.append(sum_val)
but no need for that.
A better approach will be to use numpy, which allows you to sum by axis, as it looks on list of lists like an array. Since you are learning basic python, it's too soon to learn about numpy. Just keep in mind that there is a package for handling multi-dimensions arrays and it allows it perform some actions like sum on an axis by your choice.
Edit: I've seen the other solution suggest. As both will work, I believe this solution is more "accessible" for someone who learn to program for first time. Using list comprehension is great and correct, but may be a bit confusing while first learning. Also as suggested, calling your variables list is a bad idea because it's keyword. Better names will be "my_list", "tmp_list" or something else.
Use list comprehension. Also avoid using keywords as variable names, in your case you overrode the builtin list.
# a, b -> sequence unpacking
summed = [a + b for a, b in lst] # where lst is your list of lists
# if the inner lists contain variable number of elements, a more
# concise solution would be
summed2 = [sum(seq) for seq in lst]
Read more about the powerful list comprehension here.
I have a function which returns strings. What I would like to do is get these strings and save it into a list. How can I do this?
for i in objects:
string = getstring(i)
x = 0
list[x] = string
x = x+1
You should first declare the list:
L = []
then, in the for loop, you can append items to it:
for i in objects:
string = getstring(i)
L.append(string)
It is better to use a list comprehension in this case,
my_list = [getstring(obj) for obj in objects]
Instead of creating a list and storing string in it, we are creating a list of strings, based on the objects in objects. You can do the same with map function as well
my_list = map(getstring, objects)
This takes each and every item in objects and applies getstring function to them. All the results are gathered in a list. If you are using Python 3.x, then you might want to do
my_list = list(map(getstring, objects))
Since using map is not preferred, whenever possible go with List Comprehension. Quoting from the BDFL's blog,
Curiously, the map, filter, and reduce functions that originally motivated the introduction of lambda and other functional features have to a large extent been superseded by list comprehensions and generator expressions.
I am thoroughly perplexed over the following behavior:
gap_in_y[i][j] = max((scoreMatrix[i-1][j] - dy), (gap_in_y[i-1][j] - ey))
if i == 3 and j == 1:
print gap_in_y
gap_in_x[i][j] = max((scoreMatrix[i][j-1] - dx), (gap_in_x[i][j-1] - ex))
if i == 3 and j == 1:
print gap_in_y
The two print statements produce arrays that are different in exactly one value: the value contained in gap_in_y[3][1]. Modifying gap_in_x, a separate array, shouldn't affect gap_in_y... but, somehow it does.
Any ideas? I've been going crazy trying to figure this out!
I created the two arrays in the following manner:
for i in range (0, ALength+1):
for j in range (0, BLength+1):
new.append("N/A")
gap_in_y.append(new)
gap_in_x.append(new)
new = []
It is hard to tell without seeing how gap_in_y and gap_in_x are created, but what is probably happening here is that gap_in_y[3] and gap_in_x[3] are both references to the same list, so modifying one will modify the other. You can check this out by adding the following code:
if i == 3:
print id(gap_in_y[3]) == id(gap_in_x[3])
If this ever prints True, then you know that you have copies of the same list in both of your nested lists.
When you do:
gap_in_x.append(new)
gap_in_y.append(new)
both lists will reference the same object new.
The simplest solution might be to change this to:
gap_in_x.append(new[:])
gap_in_y.append(new[:])
(assuming new is a list).
The slice operator [:] will create a copy of list new so each list will receive its own copy.
I see, when you created the array, you create a single new list, and append this same list into both the gap_in_x and gap_in_y lists. So they now contain the same list and any mutation in it will naturally be seen from either parent list.
Instead of appending new, append new[:], this will create a copy of new for each gap_in_*, as you have it now, it puts the same list into each of them.
for i in range (0, ALength+1):
for j in range (0, BLength+1):
new.append("N/A")
gap_in_y.append(new[:])
gap_in_x.append(new[:])
new = []
Other answers have pointed out the issue with the current code. I just want to suggest an alternative way of creating your lists, using list multiplication and a list comprehension rather than explicit loops and append():
gap_in_x = [["N/A"] * (BLength + 1) for _ in range(ALength + 1)]
gap_in_y = [["N/A"] * (BLength + 1) for _ in range(ALength + 1)]
Note that you don't want to use list multiplication for the outer list (e.g. [["N/A"] * BLength] * ALength) because this will cause a similar issue to what you're having already, where all of the inner lists will be copies of each other (though within the same outer array this time, not across the two). It's fine for the inner list because strings are immutable. It doesn't matter if some (or all) of the N/As reference the same object, since that object cannot modified.
I'm handling mouse clicks on objects based on the location of the object on the screen. I record the xy coord of the mouse click and see if it matches any of the objects that are allowed to be clicked on. The objects are in different lists or just single objects, but I want them in one big list so I can just loop through the whole thing once, if the click is on one of the objects, do the work, break. You can only click on one object.
First method: how i'm doing it now:
list = [obj1, obj2, obj3]
singleobj
copylist = list
copylist.append(singleobj)
for item in copylist:
if item.pos == mouseclick.pos:
doWork(item)
break
Second method: I'd rather do something like below, but obviously the list+singleobj is not valid:
for item in list+singleobj:
if item.pos == mouseclick.pos:
doWork(item)
break
Third method: Or if I absolutely had to, I could do this horrible terrible code:
list = [obj1, obj2, obj3]
foundobj = None
for item in list:
if item.pos == mouseclick.pos:
foundobj = item
break
if foundobj is None:
if singleobj.pos == mouseclick.pos:
foundobj = singleobj
#possibly repeated several times here....
if foundobj is not None:
doWork(foundobj)
The first method seems slow because I have to copy all of the (possibly many) lists and single objects into one list.
The second method seems ideal because it's compact and easy to maintain. Although, as it stands now it's simply pseudo code.
The third method is bulky and clunky.
Which method should I use? If the second, can you give the actual code?
For 2nd method you need itertools.chain
for item in itertools.chain(list, [singleobj]):
...
DrTyrsa's answer is what I was about to say about your precise question, but let me give you a few other tips:
copylist = list
copylist.append(singleobj)
this does not create a copy of the list, you might want to do copylist = list[:] or copylist = list(lst) (I changed the name here to lst, because list is a builtin. you know).
about your second method, you can do:
for item in list + [singleobj]:
...
and if you are going to use itertools, a tiny improvement is to use a tuple rather than a list to hold the extra object, as it's a little bit more lightweight:
for item in itertools.chain(list, (singleobj,)):
...
the other thing is that you should not be looping your objects to see if the coordinates match, you can have them indexed by their boundaries (in something like a BSP tree or a Quadtree) and do a faster lookup.