I'm trying to add the last item of a list onto the list my code is:
def dup_last(data):
data.append([-1])
return data
and calling for the function is:
item = dup_last([1,2,3])
print(item)
but I want my output to be within only one set of brackets like:
[1, 2, 3, 3]
data.append([-1])
Here you are appending [-1], a list with an element of -1, change it to:
data.append(data[-1])
In addition to other answers, I would also suggest to use slicing notation [:] when dealing with lists to prevent getting list index out of range errors in case there is no item:
def dup_last(data):
data.append(data[-1])
return data
The above function will raise IndexError if data is empty list:
>>> print dup_last([])
----> 2 data.append(data[-1])
3 return data
4
IndexError: list index out of range
When you update your function as follows, you no longer get that kind of error:
def dup_last(data):
data.extend(data[-1:])
return data
>>> print dup_last([])
[]
>>> print dup_last([1])
[1, 1]
>>> print dup_last([1, 2])
[1, 2, 2]
There is a good explanation in this SO question about how slicing works in Python.
You need to do data.append(data[-1]); data.append([-1]) appends a value which is a list containing only -1, so your result will be [1, 2, 3, [-1]].
Note that this will modify the list in-place, so whichever list you pass in will also have the last element duplicated, not just the list you get out (though they could be the same list).
I wouldn't use a function for this; just do data.append(data[-1]) instead of data = dup_last(data), or even dup_last(data). Also, it's probably better to just add the duplicate manually if you're working with a list literal; data = [1, 2, 3, 3] vs data = dup_last([1, 2, 3]) or similar.
Related
I am trying to use:
num_new = num[i,-1]
to get the last segment of the array. However, it returns [] when i = 0, and num = [3]
Do I have to use like num[i, len(num)]?
Is there any other attention need to pay when using -1 to retrieve array elements?
I think this is not a matter of -1, but python list slicing.
some_list[-n] means nth element of list from end of list, so you will get 5 as a result in following example:
some_list = [1, 3, 5]
last_elem = some_list[-1] # 5
And this is not a core issue of your question.
List slicing in python works with this args:
some_list[_start_:_end_:_step_]
And end th element is exclusive.
So if you are trying to [3][0:-1], this excludes last element and returns empty list.
If you want to get last segment of list, you should slice like this:
some_list = [1, 2, 3, 4, 5]
sliced_list = some_list[3:] # [4, 5]
neg_1_list = some_list[3:-1] # [4]
This will help you.
I am trying to define a function that returns a list without the first and last items in that list. However, I get this when I run the function: "TypeError: 'builtin_function_or_method' object does not support item deletion".
This is my code so far:
def middle(t):
"""returns a copy of a list with the first and last items removed
list -> list"""
t = input
del t[0]
del t[-1]
print(t)
Any help is appreciated.
t=input is assigning t to the function object input. You can't slice a function. t[1:-1] will return a new list with the first and last items removed.
You should delete the t = input line; that's assigning t to the built-in function input, which isn't an array and isn't what you want. Once you do that, you can use:
l = [0, 1, 2, 3, 4]
middle(l)
which will leave l = [1, 2, 3].
However, a better way of doing this is just to say
l = [0, 1, 2, 3, 4]
l2 = l[1:-1]
This leaves l2 as [1, 2, 3], as I assume you wanted.
If I were you, I'd go with something like
themiddlevalues = t[1:-1]
This works on any sort of sequence, and doesn't require a function. It's probably worth learning about python slice notation, as slices are important to numpy, etc. See http://codingbat.com/doc/python-strings.html, as slices work the same way across strings, lists, etc.
As I am new to programming in Python. I am trying to remove particular elements from array using for loop which looks like
a=[2,3,1,4,1,1,1,5]
n=a.count(1)
for i in range (len(a)-n):
if (a[i]==1):
del a[i]
else:
a[i]=a[i]
print (a)
I want to remove 1 from array a. But, I am getting result as:
[2, 3, 4, 1, 1, 5].
That is 1 still exists in my new array. Can somebody please answer my problem?
try like this:
a = [2,3,1,4,1,1,1,5]
a = [x for x in a if x!=1] # this is called list comprehension
note Never modify list while iterating
Use a while loop and the remove method:
a = [2, 3, 1, 4, 1, 1, 1, 5]
while 1 in a:
a.remove(1)
print a
The real answer to your question (which none of the other answers addresses) is that every time you remove an item, the index i moves past it.
in your case:
a = [2,3,1,4,1,1,1,5]
after deleting the 5th item in the original list, the pointer moves to the 6th item, and the new 5th item (the second 1 in the sequence of three 1s) is skipped.
Regarding the comment never modify a list in a loop, try to implement an in-place algorithm like Fisher-Yates without modifying the list. Never say never. Know what you're doing.
The OP changes the list in-place, not creating a new list.
There are two methods, the second is safe, the first might be faster.
a = [2, 3, 1, 4, 1, 1, 1, 5]
toremove = 1
for i in range(len(a)-1, -1, -1):
if a[i] == toremove:
del a[i]
and
a = [2, 3, 1, 4, 1, 1, 1, 5]
toremove = 1
for i in range(a.count(toremove)):
a.remove(toremove)
The second removes the element however many times it exists (before the loop). Since we are not iterating on the list, it is safe to use the remove method.
Both fragments should be O(n) (but haven't done the calculations).
You can copy a and then remove but you cannot iterate over and delete elements from the same list, if your list starts with n elements python will have n pointers to each element so removing elements from the list as your are iterating over it will cause elements to be missed.python has no way of knowing you have removed elements from the list:
a = [2,3,1,4,1,1,1,5]
for ele in a[:]:
if ele == 1:
a.remove(1)
print(a)
[2, 3, 4, 5]
You can also use reversed which returns and iterator avoiding creating a whole copy of the list at once:
a = [2,3,1,4,1,1,1,5]
for ele in reversed(a):
if ele == 1:
a.remove(1)
print(a)
[2, 3, 4, 5]
Or using a list comprehension with the [:] syntax so we actually update the original object:
a[:] = (ele for ele in a if ele != 1)
All the above are linear operations using a single pass over a.
Actually as the del statement will remove elements from your list , and as the list that you bound in your loop doesn't been update after the first deleting you remove incorrect elements from your list , so if you want to use del you need to make the list name in your loop to reference to new list , that you can use a function for this aim , but as a more python way you can just use a list comprehension:
>>> a=[2,3,1,4,1,1,1,5]
>>> a=[i for i in a if i !=1]
>>> a
[2, 3, 4, 5]
Or you can use filter :
>>> a=[2,3,1,4,1,1,1,5]
>>> a=filter(lambda x: x !=1,a)
>>> a
[2, 3, 4, 5]
I have been given the following piece of code:
def two_pair(ranks):
"""If there are two pair, return the two ranks as a
tuple: (highest, lowest); otherwise return None."""
pair = kind(2,ranks)
lowpair = kind(2, list(reversed(ranks)))
if pair and lowpair != pair:
return (pair,lowpair)
else:
return None
In the lowpair variable, why does list() need to be stated? Why can't you just say reversed(ranks). ranks is a list. Is it not already implied?
reversed returns an iterator, not a list. We need to explicitly convert that to a list, unless we just want to iterate it.
a = [1, 2, 3]
print reversed(a) # <listreverseiterator object at 0x7fc57d746790>
That is why we have to use list to get the actual reversed list, like this
print list(reversed(a)) # [3, 2, 1]
If you want shorter code you could do ranks[::-1] instead of list(reversed(ranks)).
>>> ranks = [1,2,3]
>>> ranks[::-1]
[3, 2, 1]
reversed(ranks) isn't a reversed list. It's an iterator:
>>> reversed([1, 2, 3])
<listreverseiterator object at 0x0000000001DDE9E8>
The list call is necessary to get a reversed list.
I'd make a function in python, that given a list returns a list of list, in which every element is the list given decreased by one.
Input: list_decreaser([0,3,4,5,6,7,8)
Output: [[0,3,4,5,6,7],[0,3,4,5,6],[0,3,4,5],[0,3,4],[0,3],[0]]
My attempt:
def list_decreaser(list):
listresult = []
for x in range(len(list)-1):
list.remove(list[x])
listresult.append(list)
return listresult
The code appends the same list multiple times. It should append copy of the list.
And use del list[..] instead of list.remove(list[..]) to delete an item at specific index.
def list_decreaser(xs):
listresult = []
for i in range(len(xs)-1, 0, -1): # <--- interate backward
del xs[i]
listresult.append(xs[:]) # <----
return listresult
print(list_decreaser([0,3,4,5,6,7,8]))
Or using list comprehension:
>>> xs = [0,3,4,5,6,7,8]
>>> [xs[:i] for i in range(len(xs)-1, 0, -1)]
[[0, 3, 4, 5, 6, 7], [0, 3, 4, 5, 6], [0, 3, 4, 5], [0, 3, 4], [0, 3], [0]]
BTW, don't use list as a variable name. It shadows builtin list function.
The problem is that you're appending the same list over and over again. You keep mutating the list in-place, but you're never creating a new list. So you end up with a list of N references to the same empty list.
This is the same problem discussed in two FAQ questions. I think How do I create a multidimensional list explains it best.
Anyway, what you need to do is append a new list each time through the loop. There are two ways to do that.
First, you can append a copy of the current list, instead of the list itself:
def list_decreaser(list):
listresult = []
for x in range(len(list)-1):
list.remove(list[x])
listresult.append(list[:]) # this is the only change
return listresult
This solves your problem, but it leaves a few new problems:
First, list.remove(list[x]) is a very bad idea. If you give it, say, [0, 1, 2, 0], what happens when you try to remove that second 0? You're calling list.remove(0), and there's no way the list can know you wanted the second 0 rather than the first! The right thing to do is call del list[x] or list.pop(x).
But once you fix that, you're removing the elements from the wrong side. x is 0, then 1, then 2, and so on. You remove element 0, then element 1 (which is the original element 2), then element 2 (which is the original element 4), and eventually get an IndexError. Even if you fixed the "skipping an index" issue (which is also explained in the FAQ somewhere), you'd still be removing the first elements rather than the last ones. You can fix that by turning the range around. However, there's an even easier way: Just remove the last element each time, instead of trying to figure out which x is the right thing, which you can do by specifying -1, or just calling pop with no argument. And then you can use a much simpler loop, too:
def list_decreaser(list):
listresult = []
while list:
list.pop()
listresult.append(list[:])
return listresult
Of course this appends the last, empty list, which you apparently didn't want. You can fix that by doing while len(list) >= 1, or putting an if list: listresult.append(list[:]), or in various other ways.
Alternatively, you can make new truncated lists instead of truncating and copying the same list over and over:
def list_decreaser(list):
listresult = []
while len(list):
list = list[:-1]
listresult.append(list)
return listresult
Note that in this second version, rather than changing the value stored in list, we're creating a new list and storing that new list in list.
use this
def list_decreaser(list1):
listresult = []
for i in list1:
list1 = list[:-1]
listresult.append(list1)
return listresult