-1 index in array? - python

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.

Related

Is there a function to convert a int list to a list that shows the smallest-to-largest order of the list? [duplicate]

This question already has answers here:
Sorting list based on values from another list
(20 answers)
Closed 3 years ago.
I need a function that turns a list like
[10,5,2,3,7]
to a list like
[4,2,0,1,3]
Basically a list [0,1,2,3,4...] but arranged in the order that the original list has, smallest to biggest.
I have no idea where to even start on a function like this. I have Python 3.5.2.
hiro protagonist's answer was close, but he indexed the wrong list.
>>> data = [10,5,2,3,7]
>>> sorted_list = sorted(data)
>>> [sorted_list.index(item) for item in data]
[4, 2, 0, 1, 3]
This wouldn't account for cases where you want to account for multiple occurrences and whatnot, but I'm not sure if that's required in your case.
Try this:
>>> d = [10, 5, 2, 3, 7]
>>> [sorted(d).index(i) for i in d]
[4, 2, 0, 1, 3]
This solution would work; however, there is probably a solution that is more space efficient. This solution does allow for repeat elements though.
l1 = [10, 5, 2, 3, 7] # Your list
l2 = sorted(l1) # Get the sorted version of our list.
# A dictionary containing each element and a list of the indices where they are found
element_indices = {}
for index, element in enumerate(l2):
if element not in element_indices:
element_indices[element] = [index] # Store the index for each element when it is sorted
else: # We have seen this element before
element_indices[element].append(index)
l2 = [element_indices[value].pop() for value in l1] # Change each element to its sorted equivalent index
print(l2) # [4, 2, 0, 1, 3]

Select all possible previous array/list elements

I want to select in a for loop the i element of an array/list and store up to the 4 previous elements in a list + the present element. This previous-elements list is thus updated every loop as i advances:
a=list(range(0,50))
for i in range(0,len(a)-1):
previous_4=a[i-4:i+1]
present_element=a[i]
print('The present element is {}'.format(present_element))
print('The previous list is {}'.format(previous_4))
My problem is that when running the for loop, the first 4 loops do not store any previous_4 list, not event the present element, as it is below the 0 index.
The present element is 0
The previous list is []
The present element is 1
The previous list is []
The present element is 2
The previous list is []
The present element is 3
The previous list is []
The present element is 4
The previous list is [0, 1, 2, 3, 4]
The present element is 5
The previous list is [1, 2, 3, 4, 5]
What I want is an output list of any of the 4-previous elements available in a list:
The present element is 0
The previous list is [0]
The present element is 1
The previous list is [0, 1]
The present element is 2
The previous list is [0, 1, 2]
The present element is 3
The previous list is [0, 1, 2, 3]
The present element is 4
The previous list is [0, 1, 2, 3, 4]
The present element is 5
The previous list is [1, 2, 3, 4, 5]
Is there any way to tell Python "catch me any available element of this list up to 4 elements"?
The problem is that your slicing a[i-4:i+1] is wrong because i-4 is negative at the 4 first iterations. In Python, negative index refers to the elements starting from the end of your list with a[-1] being the last element of the list a. Therefore a[-4:0] returns an empty list while a[-4:-1] would return its 3 last elements. Simply change to
previous_4 = a[max(0,i-4):i+1]
try this:
a=list(range(0,8))
previous_4=[]
for i in range(0,len(a)-1):
previous_4.append(i)
present_element=a[i]
print('The present element is {}'.format(present_element))
print('The previous list is {}'.format(previous_4))
if(len(previous_4)==5):
previous_4.pop(0)
This should work:
for i in range(0, len(a)):
if i < 4:
previous_4 = a[ : i+1]
else:
previous_4 = a[i-4: i+1]
#Kefeng91's answer is a good solution (+1) but most of the answers are poor. I'd say there is a better way, the functional way! This is the way I would do it in proper production code. It is efficient, extensible and reusable!
import collections
def get_n_at_a_time(itr, n):
d = collections.deque(maxlen=n) # double ended queue of fixed size
for elem in iterable:
d.append(elem)
yield tuple(d)
for sublist in get_n_at_time(range(50), 4):
print('the current sublist is: {}'.format(list(sublist)))
outputs
the current sublist is: [0]
the current sublist is: [0, 1]
the current sublist is: [0, 1, 2]
the current sublist is: [0, 1, 2, 3]
the current sublist is: [1, 2, 3, 4]
the current sublist is: [2, 3, 4, 5]
the current sublist is: [3, 4, 5, 6]
...
You can just append and pop from the prevous4 list as you itereate through the list
from collections import deque
a=list(range(0,50))
previous_4 = deque([])
for i in range(0,len(a)-1):
previous_4.append(a[i])
if len(previous_4) > 5:
previous_4.popleft()
present_element=a[i]
print('The present element is {}'.format(present_element))
print('The previous list is {}'.format(previous_4))
This works
a=list(range(0,50))
for i in range(0,len(a)-1):
previous_4=a[i-min(4,i):i+1] #here is the change
present_element=a[i]
print('The present element is {}'.format(present_element))
print('The previous list is {}'.format(previous_4))
Explanation:-
In your code, i-4 in previous_4=a[i-4:i+1] goes negative which is not wanted.
i.e. it should be
a[i-4:i+1] only if i>4
or else simply a[0:i+1] or a[i-i, i+1]
This is what I have done.

How to properly remove elements from array in loop using Python

I tried to remove only one element from an array and print remaining ones in a loop:
arr = [1,2,3,4,5]
for i in arr:
a = arr
a.remove(i)
print a
So I am expecting it to print this:
[2, 3, 4, 5]
[1, 3, 4, 5]
[1, 2, 3, 5]
[1, 2, 3, 4]
Why am I gettting the following results instead:
[2, 3, 4, 5]
[2, 4, 5]
[2, 4]
This is a classic problem of deep vs shallow copy.
Python copies the array by reference. So, any changes to the new variable (a in your case) will be reflected in the main array (arr). Removing element from a also remove elements from arr.
You need to use following for creating a copy.
a = arr[:]
This will not remove any elements from arr.
You've already got explanations, I'll provide an alternative - you can produce requested output without using remove at all:
arr = [1,2,3,4,5]
for i in arr:
a = [x for x in arr if x != i]
print a
(beware of non-unique elements in arr, if there are any, both this code and yours will produce unexpected results, though in different ways).
You can try this.
arr = [1, 2, 3, 4, 5, 6, 7 ]
for index, item in enumerate(arr):
print(arr[0:index] + arr[index+1:])
I think this can help you.
If you don't have any repeated value you can use this too.
for item in arr:
print(set(arr) - set([item]))
Python lists are mutable i.e. modifying operations (like list.remove()) on them do not produce a new list but modify the existing list instead so each your cycle actually permanently modifies the source list and elements are lost. You'd need to copy your whole list each time you want to modify it in order to achieve what you want, or you can create a new list with elements excluded, or, for very long lists, reconstructing by slicing is probably the most performant way:
arr = [1,2,3,4,5]
for i in range(len(arr)):
a = arr[0:i] + arr[i+1:]
print(a)

Adding a duplicate item on to a list

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.

Using for loop in Python 3.4 to remove particular element from array

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]

Categories