2013-10-07 24 views
6

Bu önemsiz bir sorun olabilir, ancak daha akıllı ve verimli çözüm yolları hakkında daha fazla bilgi edinmek istiyorum.Doğru ve Yanlış Sayım Etmenin Etkili Yolu

Öğeler listem var ve her öğenin değeri a olup, değeri ikilidir. Listedeki her öğe a == 0 varsa

  • , daha sonra sağ taraftaki değişken b = 0 ayarlayın.
  • Listedeki her öğenin a == 1 varsa, b = 1'u ayarlıyorum.
  • Listede a == 0 ve a == 1 karışımı varsa, b = 2'u ayarlıyorum.
Ben a değer türleri, takip etmek için bir dizi kullanabilirsiniz

Listede adım adım geliştirdikten sonra sette iki öğe varsa yalnızca bir öğe varsa oysa, o zaman ben, b = 2 ayarlayabilirsiniz şekilde sette sadece (0 veya 1) öğeyi alıyorum ve b'u ayarlamak için kullanın.

Daha iyi bir yolu var mı?

+3

"iyi" burada da sübjektif olup en sık vurmak bekliyoruz 3 olgunun üzerinde biraz bağlıdır ve hatta bağlı olabilir listenin uzunluğu vb. – mgilson

+0

@mgilson, iyi puanlar. Hangi dava (lar) ın diğerlerinden daha sık ortaya çıkacağını bilmiyorum ve "a" özelliği kullanıcılardan gelen girdilere göre belirlenir. Listenin uzunluğunun kısa olacağını biliyorum, yani <= 1000 öğe. – ChrisG

cevap

18

any ve all'u kullanmanızı öneririm. Bunun yararının, akıllılık veya verimlilikten ziyade okunabilirlik olduğunu söyleyebilirim. Örneğin:

>>> vals0 = [0, 0, 0, 0, 0] 
>>> vals1 = [1, 1, 1, 1, 1] 
>>> vals2 = [0, 1, 0, 1, 0] 
>>> def category(vals): 
...  if all(vals): 
...   return 1 
...  elif any(vals): 
...   return 2 
...  else: 
...   return 0 
... 
>>> category(vals0) 
0 
>>> category(vals1) 
1 
>>> category(vals2) 
2 

Bu biraz kısaltılabilir isterseniz: Bu doğru veya yanlış sahip olarak (Python 3 veya __bool__) __nonzero__ tarafından yorumlanabilir şeyle çalışır

>>> def category(vals): 
...  return 1 if all(vals) else 2 if any(vals) else 0 
... 

değer.

+0

+1 ISP'mn ölmeye karar vermemiş olması durumunda, cevabım size birkaç dakika sürebilirdi. :-) (kod golf olan tek liner hariç). –

+0

nah, bu kod golf değil, o korkunç uzun parametre adı görebilirsiniz? –

2

Ayrıca kümeleri de kullanabilirsiniz.

s = set([i.a for i in your_list]) 
if len(s) == 1: 
    b = s.pop() 
else: 
    b = 2 
+1

Bir küme nesnesi, dizinlemeyi desteklemiyor. 'Next (iter (s))' seçeneğini kullanın. Ayrıca, neden i.a? – Noctua

+0

i.a, basit bir şekilde, soru listesinde belirtildiği gibi nesnelerin listesinden bir değer çıkardı: "Öğelerin bir listesi var ve her öğenin değeri bir ikili olan bir özelliğe sahip." – bcollins

+0

Evet, yorum için teşekkürler Noctua. Dizin indekslemeyi desteklemez. Inline koşullu bazı garip davranışlar görüyordum ve onu kaldırdım. Bence her/en iyi cevabı en iyi – bcollins

26

bir liste boyunca geçiş ve ek bir veri yapıları inşa:

def zot(bs): 
    n, s = len(bs), sum(bs) 
    return 1 if n == s else 2 if s else 0 
+0

hoşuma gitti. zot ne anlama geliyor? sıfır-bir-iki? – bcollins

+1

Bu, köşe durumuna 'bs == [] 'dikkat çekiyor. Çözümlerimizin aynı şekilde ele alması ilginçtir ('zot' ve 'kategori' her ikisi de 1’i döndürür), fakat doğru yanıt olup olmadığından emin değilim. all ([]) '' True' döndürürken, '' '' ('' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' döndürmüş olurdu. – senderle

+0

Bence problem cümlesi çelişkilidir: boş bir giriş için, hepsi 0 ve hepsi de 1'dir. Bu yüzden iki doğru cevabın toplamını döndürürüz ;-) –

1

iki mantıksal hasZero ve hasOne değişkenler tanımlamak ve karşılık gelen bir değer araya ise liste yineleme sırasında True için ayarlayabilir . b = 2 ise hasZero and hasOne, ise sadece hasOne ve b = 0 ise sadece hasZero.

Başka bir yol: Listedeki tüm a değerlerini toplayabilirsiniz. sumA == len(list) ise,, sumA == 0 ise b = 0 ve 0 < sumA < len(list) ise b = 2.

15

Biri kod golf söz yüzden @ senderle en üstünde bir varyasyon duramazlar:

[0,2,1][all(vals) + any(vals)] 

Kısa açıklama: Bu endekse kendi tamsayı eşdeğerleri olarak istenen yanıtların bir listesini boole değerleri kullanır. all doğruysa, any da doğru olması gerekir, bu nedenle toplamları 2 olur.any tek başına 1 verir ve hiçbir eşleşme 0 verir. Bu indeksler, karşılık gelen değerleri listeden döndürür.

orijinal şartlar sadece any + all

+0

+ 1, gerçekten pythonic yolu :) – kasitan

1

Kısa devre çözümün tamsayı dönmek için daha basit olurdu all için any ve 2 için 1 kullanmak üzere modifiye olmuş olabilir. Muhtemelen Python'da yapabileceğiniz en verimli yol.

DÜZENLEME: Açıklamalarda öneri olarak any ve all dahildir.

EDIT2: Artık bir liner.

b = 1 if all(A) else 2 if any(A) else 0 
+1

Yerleşik 'herhangi()' ve 'tüm()' fonksiyonları kısa devre ve muhtemelen daha hızlıdır herhangi bir açık döngü-öğeleri. – martineau

+0

@martineau Açık for-looping, C 'de,' any 've 'all' ile aynı şekilde uygulanır. Yinelemenin neden yöntemlerden daha yavaş olacağını anlamıyorum. – Shashank

+0

Döngü C'ye aynı şekilde uygulanmaz. – martineau

0

Bu senderle önerisine benzer, ancak nesnelerin a özelliklerine erişmek için yazılı olduğu.

from random import randint 

class Item(object): 
    def __init__(self, a): 
     self.a = a 

all_zeros = [Item(0) for _ in xrange(10)] 
all_ones = [Item(1) for _ in xrange(10)] 
mixture = [Item(randint(0, 1)) for _ in xrange(10)] 

def check(items): 
    if all(item.a for item in items): 
     return 1 
    if any(item.a for item in items): 
     return 2 
    else: 
     return 0 

print 'check(all_zeros):', check(all_zeros) 
print 'check(all_ones):', check(all_ones) 
print 'check(mixture):', check(mixture) 
3

bir sözlük kullanma:

zonk_values = {frozenset([0]): 0, frozenset([1]): 1, frozenset([0, 1]): 2} 
def zonk(a): 
    return zonk_values[frozenset(a)] 

Bu aynı zamanda sadece listede tek bir geçiş ihtiyacı var.

+0

Doğru, tek geçişli, ancak listedeki her nesneyi ziyaret eder ve bunu yaparken bir "frozenset" oluşturur. – martineau

0

Sen listesine iter ators kullanabilirsiniz:

>>> L = [0, 0, 0, 0, 0] 
>>> L1 = [1, 1, 1, 1, 1] 
>>> L2 = [0, 1, 0, 1, 0] 
>>> def fn(i): 
...  i = iter(i) 
...  if all(i): return 1 
...  return 2 if any(i) else 0 
... 
>>> fn(L) 
0 
>>> fn(L1) 
1 
>>> fn(L2) 
2 
2
def zot(bs): 
    return len(set(bs)) if sum(bs) else 0 
İlgili konular