Is there a way to slice only the first and last item in a list?
For example; If this is my list:
>>> some_list
['1', 'B', '3', 'D', '5', 'F']
I want to do this (obviously [0,-1]
is not valid syntax):
>>> first_item, last_item = some_list[0,-1]
>>> print first_item
'1'
>>> print last_item
'F'
Some things I have tried:
In [3]: some_list[::-1]
Out[3]: ['F', '5', 'D', '3', 'B', '1']
In [4]: some_list[-1:1:-1]
Out[4]: ['F', '5', 'D', '3']
In [5]: some_list[0:-1:-1]
Out[5]: []
...
One way:
some_list[::len(some_list)-1]
A better way (Doesn't use slicing, but is easier to read):
[some_list[0], some_list[-1]]
Just thought I'd show how to do this with numpy's fancy indexing:
>>> import numpy
>>> some_list = ['1', 'B', '3', 'D', '5', 'F']
>>> numpy.array(some_list)[[0,-1]]
array(['1', 'F'],
dtype='|S1')
Note that it also supports arbitrary index locations, which the [::len(some_list)-1]
method would not work for:
>>> numpy.array(some_list)[[0,2,-1]]
array(['1', '3', 'F'],
dtype='|S1')
As DSM points out, you can do something similar with itemgetter:
>>> import operator
>>> operator.itemgetter(0, 2, -1)(some_list)
('1', '3', 'F')
first, last = some_list[0], some_list[-1]
You can do it like this:
some_list[0::len(some_list)-1]
Some people are answering the wrong question, it seems. You said you want to do:
>>> first_item, last_item = some_list[0,-1]
>>> print first_item
'1'
>>> print last_item
'F'
Ie., you want to extract the first and last elements each into separate variables.
In this case, the answers by Matthew Adams, pemistahl, and katrielalex are valid. This is just a compound assignment:
first_item, last_item = some_list[0], some_list[-1]
But later you state a complication: "I am splitting it in the same line, and that would have to spend time splitting it twice:"
x, y = a.split("-")[0], a.split("-")[-1]
So in order to avoid two split() calls, you must only operate on the list which results from splitting once.
In this case, attempting to do too much in one line is a detriment to clarity and simplicity. Use a variable to hold the split result:
lst = a.split("-")
first_item, last_item = lst[0], lst[-1]
Other responses answered the question of "how to get a new list, consisting of the first and last elements of a list?" They were probably inspired by your title, which mentions slicing, which you actually don't want, according to a careful reading of your question.
AFAIK are 3 ways to get a new list with the 0th and last elements of a list:
>>> s = 'Python ver. 3.4'
>>> a = s.split()
>>> a
['Python', 'ver.', '3.4']
>>> [ a[0], a[-1] ] # mentioned above
['Python', '3.4']
>>> a[::len(a)-1] # also mentioned above
['Python', '3.4']
>>> [ a[e] for e in (0,-1) ] # list comprehension, nobody mentioned?
['Python', '3.4']
# Or, if you insist on doing it in one line:
>>> [ s.split()[e] for e in (0,-1) ]
['Python', '3.4']
The advantage of the list comprehension approach, is that the set of indices in the tuple can be arbitrary and programmatically generated.
Python 3 only answer (that doesn't use slicing or throw away the rest of the list
, but might be good enough anyway) is use unpacking generalizations to get first
and last
separate from the middle:
first, *_, last = some_list
The choice of _
as the catchall for the "rest" of the arguments is arbitrary; they'll be stored in the name _
which is often used as a stand-in for "stuff I don't care about".
Unlike many other solutions, this one will ensure there are at least two elements in the sequence; if there is only one (so first
and last
would be identical), it will raise an exception (ValueError
).
What about this?
>>> first_element, last_element = some_list[0], some_list[-1]
Actually, I just figured it out:
In [20]: some_list[::len(some_list) - 1]
Out[20]: ['1', 'F']
This isn't a "slice", but it is a general solution that doesn't use explicit indexing, and works for the scenario where the sequence in question is anonymous (so you can create and "slice" on the same line, without creating twice and indexing twice): operator.itemgetter
import operator
# Done once and reused
first_and_last = operator.itemgetter(0, -1)
...
first, last = first_and_last(some_list)
You could just inline it as (after from operator import itemgetter
for brevity at time of use):
first, last = itemgetter(0, -1)(some_list)
but if you'll be reusing the getter a lot, you can save the work of recreating it (and give it a useful, self-documenting name) by creating it once ahead of time.
Thus, for your specific use case, you can replace:
x, y = a.split("-")[0], a.split("-")[-1]
with:
x, y = itemgetter(0, -1)(a.split("-"))
and split
only once without storing the complete list
in a persistent name for len
checking or double-indexing or the like.
Note that itemgetter
for multiple items returns a tuple
, not a list
, so if you're not just unpacking it to specific names, and need a true list
, you'd have to wrap the call in the list
constructor.
More General Case: Return N points from each end of list
The answers work for the specific first and last, but some, like myself, may be looking for a solution that can be applied to a more general case in which you can return the top N points from either side of the list (say you have a sorted list and only want the 5 highest or lowest), i came up with the following solution:
In [1]
def GetWings(inlist,winglen):
if len(inlist)<=winglen*2:
outlist=inlist
else:
outlist=list(inlist[:winglen])
outlist.extend(list(inlist[-winglen:]))
return outlist
and an example to return bottom and top 3 numbers from list 1-10:
In [2]
GetWings([1,2,3,4,5,6,7,8,9,10],3)
#Out[2]
#[1, 2, 3, 8, 9, 10]
You can use something like
y[::max(1, len(y)-1)]
if you really want to use slicing. The advantage of this is that it cannot give index errors and works with length 1 or 0 lists as well.
Another python3 solution uses tuple unpacking with the "*" character:
first, *_, last = range(1, 10)
These are all interesting but what if you have a version number and you don't know the size of any one segment in string from and you want to drop the last segment. Something like 20.0.1.300 and I want to end up with 20.0.1 without the 300 on the end. I have this so far:
str('20.0.1.300'.split('.')[:3])
which returns in list form as:
['20', '0', '1']
How do I get it back to into a single string separated by periods
20.0.1
I found this might do this:
list[[0,-1]]
def recall(x):
num1 = x[-4:]
num2 = x[::-1]
num3 = num2[-4:]
num4 = [num3, num1]
return num4
Now just make an variable outside the function and recall the function : like this:
avg = recall("idreesjaneqand")
print(avg)
来源:https://stackoverflow.com/questions/12218796/python-slice-first-and-last-element-in-list