33

A list:

a = ['a', 'b', 'c', 3, 4, 'd', 6, 7, 8]

I want a list using a subset of a using a[0:2],a[4], a[6:],

that is I want a list ['a', 'b', 4, 6, 7, 8]

falsetru
  • 336,967
  • 57
  • 673
  • 597
user2783615
  • 749
  • 3
  • 10
  • 16

3 Answers3

36

Suppose

a = ['a', 'b', 'c', 3, 4, 'd', 6, 7, 8]

and the list of indexes is stored in

b= [0, 1, 2, 4, 6, 7, 8]

then a simple one-line solution will be

c = [a[i] for i in b]
G. Cohen
  • 484
  • 4
  • 4
34

Try new_list = a[0:2] + [a[4]] + a[6:].

Or more generally, something like this:

from itertools import chain
new_list = list(chain(a[0:2], [a[4]], a[6:]))

This works with other sequences as well, and is likely to be faster.

Or you could do this:

def chain_elements_or_slices(*elements_or_slices):
    new_list = []
    for i in elements_or_slices:
        if isinstance(i, list):
            new_list.extend(i)
        else:
            new_list.append(i)
    return new_list

new_list = chain_elements_or_slices(a[0:2], a[4], a[6:])

But beware, this would lead to problems if some of the elements in your list were themselves lists. To solve this, either use one of the previous solutions, or replace a[4] with a[4:5] (or more generally a[n] with a[n:n+1]).

Martin Tournoij
  • 24,971
  • 24
  • 101
  • 136
rlms
  • 10,104
  • 8
  • 43
  • 58
  • Thanks the second solution is great – user2783615 Oct 08 '13 at 16:02
  • Thanks again for the function -- what's the usage of * in the arguments? – user2783615 Oct 08 '13 at 16:06
  • It (I believe it is called the splat operator) is used so you can have an arbitrary amount of arguments to a function. See this: http://stackoverflow.com/questions/3394835/args-and-kwargs – rlms Oct 08 '13 at 16:08
  • @user2783615 No problem (although I would advise that you take care with that solution, as it fails for lists of lists). – rlms Oct 08 '13 at 16:09
1

The following definition might be more efficient than the first solution proposed

def new_list_from_intervals(original_list, *intervals):
    n = sum(j - i for i, j in intervals)
    new_list = [None] * n
    index = 0
    for i, j in intervals :
        for k in range(i, j) :
            new_list[index] = original_list[k]
            index += 1

    return new_list

then you can use it like below

new_list = new_list_from_intervals(original_list, (0,2), (4,5), (6, len(original_list)))
Mmmh mmh
  • 5,186
  • 3
  • 19
  • 29