0

If I have a list of several lists (of floats) like

list = [
       [111, 111, 4523.123, 111, 111],
       [111, 111, 4526.15354, 111, 111],
       [111, 111, 4580.112, 111, 111],
       ]

How can I get the third column without using loops? If it were a matrix in matlab I would do list(:,3).

caesar
  • 185
  • 4
  • Replace list with lst (i.e. don't use built-in functions as variable names). Then 3rd column is: list(zip(*lst))[2] – DarrylG Jan 02 '20 at 14:26
  • @DarrylG should be `list(list(zip(*lst))[2])` – Devesh Kumar Singh Jan 02 '20 at 14:27
  • Whatever answer you get, keep in mind it *will* use loops *somewhere*. Whether or not they will be explicit or written in Python or C that's another question, and I'm sure that also matlab's `list(:,3)` is also using a loop somewhere – DeepSpace Jan 02 '20 at 14:28
  • @daveshkumarsingh--yes, caught it just before seeing your message by loooking at the first answer. – DarrylG Jan 02 '20 at 14:28
  • @DeveshKumarSingh--list(list(zip(*lst))[2]) and list(zip(*lst))[2] produces the same result. We need list(zip(...)) but why would you need list(list(...)))? – DarrylG Jan 02 '20 at 14:30

5 Answers5

1

You could certainly use Numpy to help you achieve this.

import numpy as np
list = np.array([
       [111, 111, 4523.123, 111, 111],
       [111, 111, 4526.15354, 111, 111],
       [111, 111, 4580.112, 111, 111],
       ])
list[:,2]

I don't think you can achieve this with the native python list without using any loops.

velociraptor11
  • 576
  • 1
  • 5
  • 10
1

Using zip to transpose columns to rows, then selecting the 3rd sublist (row)

lst = [
       [111, 111, 4523.123, 111, 111],
       [111, 111, 4526.15354, 111, 111],
       [111, 111, 4580.112, 111, 111],
       ]

3rd column:

list(zip(*lst))[2] 
DarrylG
  • 16,732
  • 2
  • 17
  • 23
  • `list(zip(...))` are probably two loops, one for sure. – Adirio Jan 02 '20 at 14:34
  • @Adirio--no loops normally mean no for loops. All these solutions uses builtin function which uses loops internally. – DarrylG Jan 02 '20 at 14:37
  • Yes, I agree, just pointing it out that, as @DeepSpace commented in several places in this question, not having explicit loops doesn't mean there are no loops. – Adirio Jan 02 '20 at 15:14
0

Numpy is a very good solution:

import numpy as np


list = [
       [111, 111, 4523.123, 111, 111],
       [111, 111, 4526.15354, 111, 111],
       [111, 111, 4580.112, 111, 111],
       ]

np_list = np.array(list)[:,2]

For more complicated data manipulation, I would recommend using pandas.DataFrame (https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)

If you must use list, you can try list comprehension. This is technically a loop, but use much shorter syntax and is a very pythonic way of working with collections. It also saves you from a need of using external libraries:

>>> list = [
...        [111, 111, 4523.123, 111, 111],
...        [111, 111, 4526.15354, 111, 111],
...        [111, 111, 4580.112, 111, 111],
...        ]
>>> l = [ x[2] for x in list ]
>>> l
[4523.123, 4526.15354, 4580.112]
Alexander Pushkarev
  • 1,075
  • 6
  • 19
0

Using the library numpy:

import numpy as np


list = [
       [111, 111, 4523.123, 111, 111],
       [111, 111, 4526.15354, 111, 111],
       [111, 111, 4580.112, 111, 111],
       ]

np_list = np.array(list)
third_col = np_list[:,2] # counting starts from 0

Dante
  • 73
  • 8
0

There is not, but you can make a class that handles it. Basically you need to override the __getitem__ method of the class, check if the passed value is a tuple, and in that case return accordingly:

class MatlabList(list):
    def __init__(self, *args):
        if len(args) > 1:
            return super().__init__(args)
        return super().__init__(*args)

    def __getitem__(self, item):
        if isinstance(item, tuple):
            # Remove the non-needed tuple in case it onle has one element
            if len(item) == 1:
                return self[item[0]]
            if isinstance(item[0], slice):
                return MatlabList(map(lambda x: x[item[1:]], self[item[0]]))
            return self[item[0]][item[1:]]
        return super().__getitem__(item)

lst = MatlabList(
    MatlabList(111, 111, 4523.123, 111, 111),
    MatlabList(111, 111, 4526.15354, 111, 111),
    MatlabList(111, 111, 4580.112, 111, 111),
)

lst[1,2]  # cell at 2nd row, 3rd column
lst[1,:]  # 2nd row
lst[:,2]  # 3rd column
Adirio
  • 5,040
  • 1
  • 14
  • 26
  • `MatlabList(lst)[2]` returns the third row, not the third column – DeepSpace Jan 02 '20 at 14:38
  • 1
    @DeepSpace that is also Matlab's behavior, it should be `[:, 2]` if you want the column. – Adirio Jan 02 '20 at 14:50
  • I realized that `[:, 2]` won't work either as the first index will return a list and the second subscript needs to be applied to each. Will try to fix. – Adirio Jan 02 '20 at 14:59
  • 1
    Could you show the usage syntax of retrieving the 3rd column using your solution? Thanks. – DarrylG Jan 02 '20 at 15:03
  • @DarrylG done, I had to fix an issue when slices were provided for rows instead of columns, so thank you for your comment. – Adirio Jan 02 '20 at 15:12