簡體   English   中英

從集合中選擇單個項目:Python

[英]select single item from a collection : Python

我創建了一個實用程序函數來從生成器表達式返回預期的單個項目

print one(name for name in ('bob','fred') if name=='bob')

這是一個很好的方法嗎?

def one(g):
    try:
        val = g.next()
        try:
            g.next()
        except StopIteration:
            return val
        else:
            raise Exception('Too many values')
    except StopIteration:
        raise Exception('No values')

一個更簡單的解決方案是使用元組解包。 這已經做了你想要的一切,包括檢查它只包含一個項目。

單項:

 >>> name, = (name for name in ('bob','fred') if name=='bob')
 >>> name
 'bob'

過多的物品:

>>> name, = (name for name in ('bob','bob') if name=='bob')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack

沒有項目:

>>> name, = (name for name in ('fred','joe') if name=='bob')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: need more than 0 values to unpack

對於那些使用或對第三方庫感興趣的人, more_itertools實現了一個具有本機錯誤處理的工具:

> pip install more_itertools

import more_itertools as mit


mit.one(name for name in ("bob", "fred") if name == "bob")
# 'bob'

mit.one(name for name in ("bob", "fred", "bob") if name == "bob")
# ValueError: ...

mit.one(name for name in () if name == "bob")
# ValueError: ...

有關詳細信息,請參閱more_itertools文檔 底層源代碼與接受的答案類似。

簡單方法:

print (name for name in ('bob', 'fred') if name == 'bob').next()

如果在有多個值時確實需要錯誤,則需要一個函數。 我能想到的最簡單的是( EDITED也可以使用列表):

def one(iterable):
    it = iter(iterable)
    val = it.next()
    try:
        it.next()
    except StopIteration:
        return val
    else:
        raise Exception('More than one value')

看看itertools.islice()方法。

>>> i2=itertools.islice((name for name in ('bob','fred') if name=='bob'),0,1,1)
>>> i2.next()
'bob'
>>> i2.next()
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
StopIteration
>>> 

該模塊實現了許多迭代器構建塊,其靈感來自Haskell和SML編程語言的構造。 每個都以適合Python的形式重鑄。

該模塊標准化了一組核心的快速,內存有效的工具,這些工具本身或組合使用。 標准化有助於避免在許多不同的人創建他們自己的略有不同的實現時出現的可讀性和可靠性問題,每個實現都有自己的怪癖和命名約定。

這些工具可以很容易地相互結合。 這使得在純Python中簡潔有效地構建更專業的工具變得容易。

你的意思是?

def one( someGenerator ):
    if len(list(someGenerator)) != 1: raise Exception( "Not a Singleton" )

你想用所有額外的代碼完成什么?

這是我在one()函數中的嘗試。 我會避免顯式的.next()調用,而是使用for循環。

def one(seq):
    counter = 0
    for elem in seq:
        result = elem
        counter += 1
        if counter > 1:
            break
    if counter == 0:
        raise Exception('No values')
    elif counter > 1:
        raise Exception('Too many values')
    return result

首先,(回答實際問題!)您的解決方案將與提出的其他變體一樣正常。

我想補充一點,在這種情況下,IMO,發電機過於復雜。 如果你期望有一個值,你可能永遠不會有足夠的內存使用成為一個問題,所以我會使用明顯和更清晰:

children = [name for name in ('bob','fred') if name=='bob']
if len(children) == 0:
    raise Exception('No values')
elif len(children) > 1:
    raise Exception('Too many values')
else:
    child = children[0]

如何在帶有計數器的語法中使用Python? 類似於未知的回答。

def one(items):
    count = 0
    value = None

    for item in items:
        if count:
            raise Exception('Too many values')

        count += 1
        value = item

    if not count:
        raise Exception('No values')

    return value

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM