web-dev-qa-db-ja.com

各サブリストの最初の項目を抽出する

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

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

a1xを取り出して、それらとは別のリストを作成したいと思います。

私は試した:

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

リスト内包表記を使う

>>> lst = [['a','b','c'], [1,2,3], ['x','y','z']]
>>> lst2 = [item[0] for item in lst]
>>> lst2
['a', 1, 'x']
157
alecxe

あなたは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])
66
dawg

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

12

同じ問題を抱えていて、各ソリューションのパフォーマンスについて興味を持った。

これが%timeitです:

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

配列を変換する最初のでこぼこした方法:

%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)

第二の厄介な方法。 @dawg氏による説明もあります。

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

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

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

10
jboi

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

Like:(lstのxのx [0])を使用すると、ジェネレータオブジェクトが返されます。 like:[x [0] for 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']

私が間違っているかどうか私に知らせてください。

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

print(outputlist) 

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

1
PrabhuPrakash

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

>>> 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-listshttps://docs.python.org/3.4/tutorial/datastructures.html#list-comprehensions

0
Hendrik