4

I'd like to join a list into a string by index in Python 3.3. I can do it for items the follow each other, but I would like to access it by index only.

this works:

list = ['A', 'B', 'C', 'D']
partList = "".join(list[1:3])
-> BC

But how can I achieve this (it doesn't work):

list = ['A', 'B', 'C', 'D']
partList = "".join(list[0,3])
-> AD
hjstern
  • 117
  • 1
  • 1
  • 7
  • 5
    Don't name variables over built-in names (such as `list`). You'll save yourself a lot of trouble. – Henry Keiter Oct 24 '13 at 18:03
  • 1
    `my_list[0:4:3]` works for this specific case, but is... unappealing. Any reason you specifically want a slice? – Wooble Oct 24 '13 at 18:05
  • These two questions might be helpful: [question 1](http://stackoverflow.com/questions/13706258/passing-python-slice-syntax-around-to-functions) and [question 2](http://stackoverflow.com/questions/13842060/python-shorter-syntax-for-slices-with-gaps) – ely Oct 24 '13 at 18:23

2 Answers2

10

You can't slice lists into arbitrary chunks using slice notation. Probably your best bet for the general case is to use a list of indices to build a list comprehension.

mylist = ['A', 'B', 'C', 'D'] # the full list
indices = [0, 3] # the indices of myList that you want to extract

# Now build and join a new list comprehension using only those indices.
partList = "".join([e for i, e in enumerate(mylist) if i in indices])
print(partList) # >>> AD

As pointed out in the comments by DSM, if you're concerned with efficiency and you know your list of indices will be "friendly" (that is, it won't have any indices too big for the list you're cutting up), you can use a simpler expression without enumerate:

partList = "".join([mylist[i] for i in indices])
Community
  • 1
  • 1
Henry Keiter
  • 16,863
  • 7
  • 51
  • 80
  • you could easily wrap this into a generator/function if you're looking for something more concise. – Corley Brigman Oct 24 '13 at 18:09
  • I think this is a rare case where `enumerate` doesn't add much; cf. `''.join([mylist[i] for i in indices])`. – DSM Oct 24 '13 at 18:10
  • @DSM That was actually the first thing I wrote, but I went with `enumerate` to allow for indices outside the length of the list (say, if some index list is being reused for slicing a bunch of different lists that may or not be of the same length for whatever reason). – Henry Keiter Oct 24 '13 at 18:13
  • With a list, though, you've made it an O(N^2) op [well, N*K] -- we could make `indices` a set, but then we lose the possibility for out-of-order access. There's always `operator.itemgetter`, too.. ;^) – DSM Oct 24 '13 at 18:14
1

What you are intending to perform is not slicing but selecting.

The closest possibility, I can think of is to use operator.itemgetter

>>> from operator import itemgetter
>>> mylist = ['A', 'B', 'C', 'D']
>>> ''.join(itemgetter(0,3)(mylist))
'AD'

If you need to use a variable, then use a splat operator

index = (0,3)
''.join(itemgetter(*index)(mylist))
Abhijit
  • 62,056
  • 18
  • 131
  • 204
  • This looks what I am looking for. But I would like to use a variable for the indices '0,3' so that I can select any combination of indizes through a variable. I have tried: index = '0,3' or Index = [1,2] but the formula needs intividual integers separated by comma. I also would like to keep the number of indices flexible so that I could use 1,2,3 at another location. What would you suggest? – hjstern Oct 25 '13 at 08:15