各サブリストの最初のアイテムを抽出する


146

リストのリストの各サブリストの最初の項目を抽出し、それを新しいリストに追加する最良の方法は何でしょうか。だから私が持っている場合:

lst = [[a,b,c], [1,2,3], [x,y,z]]

そして、私は引き出すしたいa1そしてx、それらとは別のリストを作成します。

私は試した:

lst2.append(x[0] for x in lst)

1
あなたのコードはほぼ正しいです。唯一の問題はリスト内包表記の使い方です。
Abhishek Mittal 2014

回答:



83

あなたはzipを使うことができます:

>>> lst=[[1,2,3],[11,12,13],[21,22,23]]
>>> zip(*lst)[0]
(1, 11, 21)

または、zipリストを生成しないPython 3 :

>>> list(zip(*lst))[0]
(1, 11, 21)

または、

>>> next(zip(*lst))
(1, 11, 21)

または、(私のお気に入り)numpyを使用します:

>>> import numpy as np
>>> a=np.array([[1,2,3],[11,12,13],[21,22,23]])
>>> a
array([[ 1,  2,  3],
       [11, 12, 13],
       [21, 22, 23]])
>>> a[:,0]
array([ 1, 11, 21])

反対票を投じていませんが、最初のコードスニペット(zip)は、「 'zip'オブジェクトは添え字付けできません」を生成します。Jupyter上のPython 3.6。
jboi 2018年

@jboi:list最初にラップするか、を使用しますnext。ありがとう
dawg 2018年

20

同じ問題があり、各ソリューションのパフォーマンスに興味を持った。

ここにあります%timeit

import numpy as np
lst = [['a','b','c'], [1,2,3], ['x','y','z']]

配列を変換する最初のnumpy-way:

%timeit list(np.array(lst).T[0])
4.9 µs ± 163 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

リスト内包表記を使用した完全ネイティブ(@alecxeで説明):

%timeit [item[0] for item in lst]
379 ns ± 23.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

使用する別のネイティブな方法zip(@dawgで説明):

%timeit list(zip(*lst))[0]
585 ns ± 7.26 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

2番目の派手な方法。@dawgでも説明されています:

%timeit list(np.array(lst)[:,0])
4.95 µs ± 179 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

驚いたことに(少なくとも、私にとっては)リスト内包表記を使用したネイティブの方法は、numpyの方法よりも最も速く、約10倍高速です。finalなしで2つのnumpy-wayを実行すると、list約1 µs節約できますが、これはまだ10倍の差です。

各コードスニペットをへの呼び出しで囲んだときlen、ジェネレータが最後まで実行されることを確認するため、タイミングは同じままでした。


4
配列を作成するとかなりのオーバーヘッドがあります。
hpaulj 2018

1
hpauljに同意します。numpy配列から始める場合、[:, 0]の方が高速です。試してみましょう:lst = np.array([['a'、 'b'、 'c']、[1,2,3]、['x'、 'y'、 'z']])、次にlst [:、0]。サンプルのタイムトライアルでの変換は、リストの理解に不当な利点をもたらします。したがって、可能であれば、スピードが最終的な目標である場合は、numpy配列を使用してデータを格納します。Numpyはほとんど常に高速です。スピードを重視して作られています。
spacedustpi 2018年

13

Pythonには、リストの特定のインデックスにあるアイテムを返すitemgetterという関数が含まれています。

from operator import itemgetter

itemgetter()関数に、取得するアイテムのインデックスを渡します。最初のアイテムを取得するには、itemgetter(0)を使用します。理解しておくべき重要なことは、itemgetter(0)自体が関数を返すことです。その関数にリストを渡すと、特定のアイテムを取得します。

itemgetter(0)([10, 20, 30]) # Returns 10

これは、最初の引数として関数を取り、2番目の引数としてリスト(またはその他の反復可能オブジェクト)をとるmap()と組み合わせるときに便利です。イテラブル内の各オブジェクトで関数を呼び出した結果を返します。

my_list = [['a', 'b', 'c'], [1, 2, 3], ['x', 'y', 'z']]
list(map(itemgetter(0), my_list)) # Returns ['a', 1, 'x']

map()はジェネレータを返すため、結果はlist()に渡されて実際のリストが取得されます。要約すると、タスクは次のように実行できます。

lst2.append(list(map(itemgetter(0), lst)))

これは、リスト内包表記を使用する代わりの方法であり、どの方法を選択するかは、コンテキスト、読みやすさ、および設定に大きく依存します。

詳細:https : //docs.python.org/3/library/operator.html#operator.itemgetter


2

あなたのコードはほぼ正しいです。唯一の問題はリスト内包表記の使い方です。

like:(lstのxに対してx [0])を使用すると、ジェネレータオブジェクトが返されます。like:[x [0] for x in lst]を使用すると、リストが返されます。

リスト内包表記の出力をリストに追加すると、リスト内包表記の出力はリストの単一の要素になります。

lst = [["a","b","c"], [1,2,3], ["x","y","z"]]
lst2 = []
lst2.append([x[0] for x in lst])
print lst2[0]

lst2 = [['a'、1、 'x']]

lst2 [0] = ['a'、1、 'x']

私が間違っている場合はお知らせください。


1
lst = [['a','b','c'], [1,2,3], ['x','y','z']]
outputlist = []
for values in lst:
    outputlist.append(values[0])

print(outputlist) 

出力: ['a', 1, 'x']


0

既存のリストがあると言っていました。だから私はそれで行きます。

>>> lst1 = [['a','b','c'], [1,2,3], ['x','y','z']]
>>> lst2 = [1, 2, 3]

現在、ジェネレーターオブジェクトを2番目のリストに追加しています。

>>> lst2.append(item[0] for item in lst)
>>> lst2
[1, 2, 3, <generator object <genexpr> at 0xb74b3554>]

しかし、おそらく最初の項目のリストにしたいでしょう

>>> lst2.append([item[0] for item in lst])
>>> lst2
[1, 2, 3, ['a', 1, 'x']]

ここで、最初のアイテムのリストを既存のリストに追加しました。アイテムのリストではなく、テーマ自体を既存のものに追加する場合は、list.extendを使用します。その場合は、ジェネレーターの追加について心配する必要はありません。extendは、そのジェネレーターを使用して、そこから取得した各項目を追加し、現在のリストを拡張します。

>>> lst2.extend(item[0] for item in lst)
>>> lst2
[1, 2, 3, 'a', 1, 'x']

または

>>> lst2 + [x[0] for x in lst]
[1, 2, 3, 'a', 1, 'x']
>>> lst2
[1, 2, 3]

https://docs.python.org/3.4/tutorial/datastructures.html#more-on-lists https://docs.python.org/3.4/tutorial/datastructures.html#list-comprehensions


1
あなたの答えは、OPが望んでいるように聞こえますが、完璧ですappendが、問題の単語が混乱を引き起こしていると思います。それは彼/彼女が単にあなたのソリューションのリスト理解部分を望んでいるようです。
beroe 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.