Accessing non-consecutive elements of a list or string in python

后端 未结 5 1986
难免孤独
难免孤独 2020-12-28 15:14

As far as I can tell, this is not officially not possible, but is there a \"trick\" to access arbitrary non-sequential elements of a list by slicing?

For example:

相关标签:
5条回答
  • 2020-12-28 15:55

    None of the other answers will work for multidimensional object slicing. IMHO this is the most general solution (uses numpy):

    numpy.ix_ allows you to select arbitrary indices in all dimensions of an array simultaneously.

    e.g.:

    >>> a = np.arange(10).reshape(2, 5) # create an array
    >>> a
    array([[0, 1, 2, 3, 4],
           [5, 6, 7, 8, 9]])
    >>> ixgrid = np.ix_([0, 1], [2, 4]) # create the slice-like grid
    >>> ixgrid
    (array([[0],
           [1]]), array([[2, 4]]))
    >>> a[ixgrid]                       # use the grid to slice a
    array([[2, 4],
           [7, 9]])
    
    0 讨论(0)
  • 2020-12-28 16:02

    If you can use numpy, you can do just that:

    >>> import numpy
    >>> the_list = numpy.array(range(0,101,10))
    >>> the_indices = [2,5,7]
    >>> the_subset = the_list[the_indices]
    >>> print the_subset, type(the_subset)
    [20 50 70] <type 'numpy.ndarray'>
    >>> print list(the_subset)
    [20, 50, 70]
    

    numpy.array is very similar to list, just that it supports more operation, such as mathematical operations and also arbitrary index selection like we see here.

    0 讨论(0)
  • 2020-12-28 16:04

    Something like this?

    def select(lst, *indices):
        return (lst[i] for i in indices)
    

    Usage:

    >>> def select(lst, *indices):
    ...     return (lst[i] for i in indices)
    ...
    >>> L = range(0,101,10)
    >>> a, b = select(L, 2, 5)
    >>> a, b
    (20, 50)
    

    The way the function works is by returning a generator object which can be iterated over similarly to any kind of Python sequence.

    As @justhalf noted in the comments, your call syntax can be changed by the way you define the function parameters.

    def select(lst, indices):
        return (lst[i] for i in indices)
    

    And then you could call the function with:

    select(L, [2, 5])
    

    or any list of your choice.

    Update: I now recommend using operator.itemgetter instead unless you really need the lazy evaluation feature of generators. See John Y's answer.

    0 讨论(0)
  • 2020-12-28 16:05

    Probably the closest to what you are looking for is itemgetter (or look here for Python 2 docs):

    >>> L = list(range(0, 101, 10))  # works in Python 2 or 3
    >>> L
    [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
    >>> from operator import itemgetter
    >>> itemgetter(2, 5)(L)
    (20, 50)
    
    0 讨论(0)
  • 2020-12-28 16:08

    Just for completeness, the method from the original question is pretty simple. You would want to wrap it in a function if L is a function itself, or assign the function result to a variable beforehand, so it doesn't get called repeatedly:

    [L[x] for x in [2,5]]
    

    Of course it would also work for a string...

    ["ABCDEF"[x] for x in [2,0,1]]
    ['C', 'A', 'B']
    
    0 讨论(0)
提交回复
热议问题