58

I am trying to dynamically get the first and last element from an array.

So, let us suppose the array has 6 elements.

test = [1,23,4,6,7,8]

If I am trying to get the first and last = 1,8, 23,7 and 4,6. Is there a way to get elements in this order? I looked at a couple of questions Link Link2. I took help of these links and I came up with this prototype..

#!/usr/bin/env python

import numpy

test = [1,23,4,6,7,8]
test1 = numpy.array([1,23,4,6,7,8])
len_test = len(test)
first_list = [0,1,2]
len_first = len(first_list)
second_list = [-1,-2,-3]
len_second = len(second_list)

for a in range(len_first):
        print numpy.array(test)[[first_list[a] , second_list[a]]]
        print test1[[first_list[a], second_list[a]]]

But this prototype won't scale for if you have more than 6 elements. So, I was wondering if there is way to dynamically get the pair of elements.

Thanks!

10 Answers 10

181

I ended here, because I googled for "python first and last element of array", and found everything else but this. So here's the answer to the title question:

a = [1,2,3]
a[0] # first element (returns 1)
a[-1] # last element (returns 3)
Sign up to request clarification or add additional context in comments.

1 Comment

The general Python problem (non-Numpy solutions) is solved more dramatically in a separate question: stackoverflow.com/questions/12218796/…
28

How about:

In [10]: arr = numpy.array([1,23,4,6,7,8])

In [11]: [(arr[i], arr[-i-1]) for i in range(len(arr) // 2)]
Out[11]: [(1, 8), (23, 7), (4, 6)]

Depending on the size of arr, writing the entire thing in NumPy may be more performant:

In [41]: arr = numpy.array([1,23,4,6,7,8]*100)

In [42]: %timeit [(arr[i], arr[-i-1]) for i in range(len(arr) // 2)]
10000 loops, best of 3: 167 us per loop

In [43]: %timeit numpy.vstack((arr, arr[::-1]))[:,:len(arr)//2]
100000 loops, best of 3: 16.4 us per loop

3 Comments

However, will drop an element for arrays with odd number of elements. If you use (len(arr)+1)//2 instead, you'll capture the middle element as (middle,middle) at the end of the results.
@isedev: We don't really know what the OP's requirements are. That said, the two approaches should cover all possibilities. :)
@NPE: I would always have even number of elements. So, that should not be a problem
11
arr = np.array([1,2,3,4])
arr[-1] # last element

Comments

5

Using Numpy's fancy indexing:

>>> test
array([ 1, 23,  4,  6,  7,  8])

>>> test[::-1]  # test, reversed
array([ 8,  7,  6,  4, 23,  1])

>>> numpy.vstack([test, test[::-1]])  # stack test and its reverse
array([[ 1, 23,  4,  6,  7,  8],
       [ 8,  7,  6,  4, 23,  1]])

>>> # transpose, then take the first half;
>>> # +1 to cater to odd-length arrays
>>> numpy.vstack([test, test[::-1]]).T[:(len(test) + 1) // 2]
array([[ 1,  8],
       [23,  7],
       [ 4,  6]])

vstack copies the array, but all the other operations are constant-time pointer tricks (including reversal) and hence are very fast.

Comments

3
>>> test = [1,23,4,6,7,8]
>>> from itertools import izip_longest
>>> for e in izip_longest(test, reversed(test)):
    print e


(1, 8)
(23, 7)
(4, 6)
(6, 4)
(7, 23)
(8, 1)

Another option

>>> test = [1,23,4,6,7,8]
>>> start, end = iter(test), reversed(test)
>>> try:
    while True:
        print map(next, [start, end])
except StopIteration:
    pass

[1, 8]
[23, 7]
[4, 6]
[6, 4]
[7, 23]
[8, 1]

2 Comments

You are creating additional copies in memory using reversed(test) which you don't need to.
@SudiptaChatterjee: reversed returns a generator and not a copy
3

You can simply use take method and index of element (Last index can be -1).

arr = np.array([1,2,3])

last = arr.take(-1)
# 3

Comments

1

How about this?

>>> import numpy
>>> test1 = numpy.array([1,23,4,6,7,8])
>>> forward = iter(test1)
>>> backward = reversed(test1)
>>> for a in range((len(test1)+1)//2):
...     print forward.next(), backward.next()
... 
1 8
23 7
4 6

The (len(test1)+1)//2 ensures that the middle element of odd length arrays is also returned:

>>> test1 = numpy.array([1,23,4,9,6,7,8]) # additional element '9' in the middle
>>> forward = iter(test1)                                                      
>>> backward = reversed(test1)
>>> for a in range((len(test1)+1)//2):
...     print forward.next(), backward.next()
1 8
23 7
4 6
9 9

Using just len(test1)//2 will drop the middle elemen of odd length arrays.

Comments

1

How about this:

xs = [1,23,4,6,7,8]
np.array(list(zip(xs[:len(xs)//2], xs[::-1])))

    array([[ 1,  8],
           [23,  7],
           [ 4,  6]])

Comments

0

This does it. Note that with an odd number of elements the one in the middle won't be included.

test = [1, 23, 4, 6, 7, 8, 5]    
for i in range(len(test)/2):
    print (test[i], test[-1-i])

Output:

(1, 5)
(23, 8)
(4, 7)

Comments

-1

Assuming the list has a even number of elements, you could do:

test = [1,23,4,6,7,8]
test_rest = reversed(test[:len(test)/2])

for n in len(test_rest):
    print [test[n], test_test[n]]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.