Slicing and appending lists leaves extra values on the end - python

I want to append the first 80% of the values in two arrays into one new array. I can figure out a work around to this issue but I came across this problem when trying to do it in one line and I'm interested in knowing if it is possible.
# I create my two arrays
a = [1,2,3,4,5]
b = [6,7,8,9,10]
# Showing what slicing a and b in this way returns
# 4 in this case is equal to 80%
a[:4]
[1, 2, 3, 4]
b[:4]
[6, 7, 8, 9]
# Append 80% of b to 80% of a
a[:4] += b[:4]
# Print a
# There is a 5 at the end which I don't want to be there :(
a
[1, 2, 3, 4, 6, 7, 8, 9, 5]
I understand that what my one line is doing is telling python to insert 80% of b, 80% of the way through a, but not actually to only keep 80% of a.
Is there a way to do this without then having to remove the last 20% of a afterwards?

What you're writing is like a[:4] = a[:4] + b[:4], you're leaving the last index of a (i.e. 5), unchanged. You could think of it a bit like an insert (without creating a nested list), i.e.
>>> a = [1,2,3,4,5]
>>> a.insert(4, b[:4])
>>> a
[1, 2, 3, 4, [6, 7, 8, 9], 5]
The solution to modify the same list as you want is to assign not just to a[:4], but to the entire list:
>>> a[:] = a[:4] + b[:4]
>>> a
[1, 2, 3, 4, 6, 7, 8, 9]

a[:4] += b[:4]
With this equation, you're basically adding the first 4 elements of b[6,7,8,9] to a[1,2,3,4], leaving the last element of a[5] untouched. You can leave out the last index of a[5] by doing
c = a[:4] + b[:4]

# I create my two arrays
a = [1,2,3,4,5]
b = [6,7,8,9,10]
a=a.copy()[:4]+b.copy()[:4]
# output [1, 2, 3, 4, 6, 7, 8, 9]
shallow copy, a reference of object is copied in other object.
It means that any changes made to a copy of object do reflect in the original objec
t. In python, this is implemented using “copy()” function.
created a shallow copy of a and b then, i am taking first 4 elements from it and
appending b element with a .

Related

Subtracting elements from array

So I am trying to delete elements from an array and do some calculations with this array. The thing is, I want to still keep a copy of the original array, so I made a new array and assigned it the values of the original array. The thing is, whenever I print out the length of the original and the new array, it gives me the same length, but it gives me the length of the new array. How do I make a new array with the same values as 'a', but without changing 'a'
a = [2, 4, 5, 7, 8, 9]
b = []
b = a
for _ in range(2):
m = min(b)
b[:] = (x for x in b if x != m)
print(len(b))
print(len(a))
Saying b = a just creates a new variable that references the existing list object. To make a copy of a list you could use the list() function or list slicing:
b = list(a)
b = a[:]
That said, to create a new list from an existing one filtering out some elements you could use a list comprehension:
from heapq import nsmallest
m = nsmallest(2, a)
b = [x for x in a if x not in m]
You are not copying - you are aliasing . You give a second name to the same array (which is a list btw). try b = a[:] this will copy it - only works if the lists content is immutable.
If your list contains other lists it will "copy" the reference to that list but not the nested lists contents - that would be a deepcopy().
If you want to remove the lowest 2 you could also resort to sorting and slicing (you list is already sorted so no sort needed)
a = [2, 4, 5, 7, 8, 9]
b = a[2:] // slice, ignore first 2 entries which are the lowest 2
c = sorted(a)[2:] // implicitly creates a new sorted list, ignore lowest 2
print(b)
print(c)
Output:
[5, 7, 8, 9]
[5, 7, 8, 9]
There is difference between list and list[:].
When reading, list is a reference to the original list, and list[:] shallow-copies the list.
When assigning, list (re)binds the name and list[:] slice-assigns, replacing what was previously in the list.
However, if the list elements are lists themselves, even list1 = list[:] has its problems. Consider:
>>> a = [[1,2,3],[4,5,6],[7,8,9]]
>>> b = a[:]
>>> b[0].remove(2)
>>> b
[[1, 3], [4, 5, 6], [7, 8, 9]]
>>> a
[[1, 3], [4, 5, 6], [7, 8, 9]]
This happens because each list element being copied to b is a list itself, and this copying of lists involves the same problem that occurs with the normal list1 = list2. The shortest way out is to explicitly copy every list element this way:
>>> a = [[1,2,3],[4,5,6],[7,8,9]]
>>> b=[[j for j in i] for i in a]
>>> b
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> b[0].remove(2)
>>> b
[[1, 3], [4, 5, 6], [7, 8, 9]]
>>> a
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Python ObjectListView -- how to split a list into two columns

I have an ObjectListView in wxPython that I would like to split into two identical lists that sit next to each other instead of one long list with a scrollbar. So, instead of:
Column 1 -- Column 2 -- Column 3
data data data
data data data
I would like it to look like this:
Column 1 -- Column 2 -- Column 3 Column 1 -- Column 2 -- Column 3
data data data data data data
Of course, with more data split evenly between them, if possible. Is there a way to accomplish this without making two separate lists? The reason I don't want to make two lists is that I have one large object list I'd like to pass it and with two lists I think I'd have to split the object in two and send a section to each list; if elegance is an option, I'd prefer it.
If you use list_B = list_A you are not making "another" list, instead you are simply saying that there are 2 names for the same list, they both point to the same thing. You can use id() to check that this is true.
>>> list_A = [1,2,3,4,5,6,7,8]
>>> id(list_A)
140229575676488
>>> list_B = list_A
>>> id(list_B)
140229575676488
>>> list_A
[1, 2, 3, 4, 5, 6, 7, 8]
>>> list_B
[1, 2, 3, 4, 5, 6, 7, 8]
>>> list_A.append(9)
>>> list_A.append(10)
>>> list_A
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> list_B
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Is it possible to insert specific sections of one list into a specific location in another list?

I'm fairly new to Python, and besides finding it useful and rather easy to understand for the most part, there are still some things I'm unclear of, ergo this question.
Is it possible to insert specific sections of one list into a specific location in another list?
Say for example, I have a list called 'a', and in this list I have the numbers 1, 3 and 5 in this format:
a = [1, 3, 5]
I also have a list called 'b' which contains the numbers 2 and 4 in this format:
b = [2, 4]
My end goal would be for list 'a' to be changed to this:
a = [1, 2, 3, 4, 5]
As you can see, this would require me to specify using indices for both lists to combine them into one list in this custom format, and I am unsure as to how I could go about this.
I unintentionally left out a major detail, and that is the fact that I wanted to make use of the 'insert' function rather than 'append'.
Yes. Just use insert() and have the second argument be a list element.
a = [1, 3, 5]
b = [2, 4]
# The first argument is the index to insert it at.
# The second is the actual item to be inserted.
a.insert(1, b[0]) # [1, 2, 3, 5]
a.insert(3, b[1]) # [1, 2, 3, 4, 5]
Note that if you just want a sorted, you can just use this:
for item in b:
a.append(item) # Order does not matter, we will sort it later
# a is currently [1, 3, 5, 2, 4] since append() adds to the end of the list
a.sort()
# a is now [1, 2, 3, 4, 5] as sort() re-ordered it
Or if you want it even simpler, concatenate them and then sort:
a = a + b # [1, 3, 5, 2, 4]
a.sort() # [1, 2, 3, 4, 5]
Let me know if this is unclear or not what you wanted.
How does this work for you?
a = [1,2,5,6,7]
b = [3,4]
for n,k in enumerate(a):
if(k<b[0]):
a = a[0:n]+b+a[n:]
break
print(a)
using the colon to slice arrays is super useful.
If you're interleaving the lists, you can zip them using izip_longest:
>>> a = [1, 3, 5]
>>> b = [2, 4]
>>> from itertools import izip_longest
>>> [c for pair in izip_longest(a, b)
... for c in pair if c is not None]
[1, 2, 3, 4, 5]

How do you append modified data from a for loop? (Python)

Thanks for checking out my question, am using Python 3 by the way, here is the code:)
scale=[1,2,3,4,5,6]
MNP = {'scale degree' : []
}
for index, value in enumerate(scale):
scale.insert(len(scale),scale[0])
del scale[0]
MNP['scale degree'].append(scale[1])
print (MNP['scale degree'])
So, my goal here is append the modified versions of a list I called scale, into a dict I called MNP. The desired output is a list ('scale degree' that takes the original number of a list (such as scale), and moves it the end of the list, at the same time, all the numbers would shift one to the left, this is what is happens if I give the command to print the scale within the function:
for index, value in enumerate(scale):
scale.insert(len(scale),scale[0])
del scale[0]
MNP['scale degree'].append(scale[1])
print (MNP['scale degree'])
[1, 2, 3, 4, 5, 6]
[2, 3, 4, 5, 6, 1]
[3, 4, 5, 6, 1, 2]
[4, 5, 6, 1, 2, 3]
[5, 6, 1, 2, 3, 4]
[6, 1, 2, 3, 4, 5]
Yet when I try to do so I encountered (yes, past tense) a problem with my understanding. See, if I execute the command:
print(scale[1])
Then it actually does print the numbers 2,3,4,5,6,1 . This is why I used the enumerate function, I thought that this may solve the problem. I thought that, maybe the index number determined somehow which list would be printed off, but this is of course is wrong, even though the output is identical, and, it's worth mentioning that am still very much a stargazed newbie. Yet I did some thinking and realized that it's merely printing off the second value of each modified list, the exact same as if I gave it a single command to print off only one version, yet being a disobedient little bugger if I ask it to append the whole blown thing.
Bloody Hell.
So, now, my question is, how do I append the modified version of the scale, and not just a single value?
Appending the scale as a whole does'st work by the way (this was also my first solution), as the output is then:
[[2, 3, 4, 5, 6, 1]]
[[3, 4, 5, 6, 1, 2], [3, 4, 5, 6, 1, 2]]
[[4, 5, 6, 1, 2, 3], [4, 5, 6, 1, 2, 3], [4, 5, 6, 1, 2, 3]]
it keeps going in this fashion until it reaches [1,2,3,4,5,6] * 6
Thanks in advance for any help, also if you may, could you recommend resources so that I can gain a basic understanding of what's playing behind the scenes? There's probably a lot I still don't understand (I mean in relation only to this problem alone, of course, in general am that close to understanding everything there is to know (haha)).
Thanks again
James
P.S how long in general should I wait till I seek help on SE? (For this particular problem, I've been dueling with if for a solid Day 1/2)
P.S.S A thanks to Borodin for pointing that the manipulation of data within a for loop is bad practice. How should this be correctly executed?
Is this the effect you're after?
>>> l = [1,2,3,4]
>>> l.append(list.pop())
[2,3,4,1]
Or if you want it unrolled a little:
>>> l = [1,2,3,4]
>>> e = list.pop()
>>> l.append(e)
[2,3,4,1]
In both cases, we remove the first element from the list and stick it on the end of the list - which I think is what you're after.
Or if you don't want to modify the original list:
>>> l = [1,2,3,4]
>>> l[1:]+[l[0]]
[2,3,4,1]
Here, we're just recombining slices - the original list is unchanged. Notice that I have to put l[0] into a list because that's the way + is implemented for lists - I can't do l[1:] + l[0].
I think this would help. It has rotate(n) which shifts the elements of the list by n places.
import collections
my_list = []
d = collections.deque([1,2,3,4,5])
for i in range(5):
d.rotate(-1)
my_list.append(d)
print my_list
Output:
[deque([1, 2, 3, 4, 5]), deque([1, 2, 3, 4, 5]), deque([1, 2, 3, 4, 5]), deque([1, 2, 3, 4, 5]), deque([1, 2, 3, 4, 5])]

Need Help in switching values in a list in python

I have a list of numbers, such as:
[1, 2, 3, 4, 5, 6]
I'm having trouble figuring out how to switch the first 2 items of the list with the last 2, or the first 3 with the last 3, and so on.
When i assign the values of the 1st two numbers to the last 2 items of the list, i then cannot assign the last 2 values (what used to be the last 2 values of the list) to the first two because the last 2 values have been lost.
If i try using another empty list and appending the last 2 values of the original list to that list, then appending the middle values, and then the first 2 values of the old list, I end up with something like this:
[[[5, 6], [3, 4], [1, 2]]]
I don't want nested lists! What I want is:
[5, 6, 3, 4, 1, 2]
Can someone help me?
>>> nums = [1, 2, 3, 4, 5, 6]
>>> nums[:2], nums[-2:] = nums[-2:], nums[:2]
>>> nums
[5, 6, 3, 4, 1, 2]
This modifies the original list but if you want a separate new list you should use the following:
>>> nums = [1, 2, 3, 4, 5, 6]
>>> swapped_nums = nums[-2:] + nums[2:-2] + nums[:2]
>>> swapped_nums
[5, 6, 3, 4, 1, 2]
Note: This won't work properly if your list has < 4 elements

Categories

Resources