2013-01-14 17 views
9

Rakamların bir listesi var ve benzersiz rakamlar içeren sayıları filtrelemek istiyorsunuz, yani her rakam yalnızca bir kez numarada gerçekleşebilir.Benzersiz rakamlar içeren sayılar nasıl filtrelenir?

Olumlu örnekler:

  • 58293,6
  • 0,1246

Olumsuz örnekler:

  • (5 iki yerde geçer) 58293.666 (6 üç kez gerçekleşir)
  • 0,12461 (1 kez gerçekleşir)

Bunu nasıl yapacaksın? Benim kendi fikrim, her bir sayıyı bir dizgeye dönüştürmek ve daha sonra dizenin karakterlerinden yapılmış kümenin boyutunun dizginin uzunluğuna eşit olup olmadığını kontrol etmektir. Bunun gibi bir şey:

def uniques(numbers): 
    for number in numbers: 
     str_number = str(number) 
     if len(set(str_number)) == len(str_number): 
      yield number 

for i in uniques(xrange(1000, 1050)): 
    print i 

1023 
1024 
1025 
1026 
1027 
1028 
1029 
1032 
1034 
1035 
1036 
1037 
1038 
1039 
1042 
1043 
1045 
1046 
1047 
1048 
1049 

ilk dizeleri tamsayıları dönüştürmeden bunu yapmanın bir yolu var mı?

+2

Geri dönüştürmeyin. Sayının dizili sürümü için başka bir değişken alın. – Matthias

+0

Özellikle girişiniz float 'içerir ... –

+3

Bunun yanı sıra, yaklaşımınızın anlaşılması kolay ve basit olduğunu düşünüyorum. Ben onunla giderdim. –

cevap

8

mı?

Evet, basamak tabanı 10 bulmak için divmod kullanabilirsiniz, ancak bu deftere yöntemle daha hızlı değildir: Kullanılması collections.Counter

def uniques2(numbers): 
    for number in numbers: 
     seen = set() 
     quotient = number 
     while quotient > 10: 
      quotient, remainder = divmod(quotient, 10) 
      if remainder in seen: 
       break 
      else: 
       seen.add(remainder) 
     else: 
      yield number 
+0

+1. Çok hoş. Tam olarak aradığım şey bu. Makinemde, senin yöntemin benim çözümümden biraz daha hızlı. Aferin. :) – pemistahl

5

Dene:

filtered_numbers = filter(predicate, numbers) 

ya: Eğer regex tabanlı bir çözüm istiyorsanız

filtered_numbers = filter(lambda n: len(repr(n)) == len(set(repr(n))), numbers) 
+1

+1 'lambda' için :) –

+1

'' str' yerine 'repr' kullanıldığında, aynı şekilde farklı bir şekilde söyleyen aynı şey – Abhijit

+1

@Abhijit, repr (1.0/7.0) ile str (1.0) arasında küçük bir fark var. Örneğin, /7.0). –

3

aşağıdaki regex dikkate

def predicate(n): 
    s = repr(n) 
    return len(s) == len(set(s)) 
filtered_numbers = [ n for n in numbers if predicate(n) ] 

veya, süzgeç işlevi isterseniz :

(?![\d.]*([\d.])[\d.]*\1)^[\d.]+$ 

Yinelenen basamak yoksa ve yinelenen bir ondalık noktası yoksa, bir dizi basamak ve süreyi eşleştirin.

Güncellemesi (teşekkürler @frb): Python bu doğru yazmanın yolu bunu yapmanın bir yolu, ilk asar ve sonra geri dönüştürmek için tamsayılar dönüştürmeden var mı

re.match(r"(?![\d.]*([\d.])[\d.]*\1)^[\d.]+$",str_number).group(0) 
+0

@frb IIUC, kaynağın bir dizi _converted_ olduğu dizedir, yani '1.1.1' oluşamaz. Her neyse, 1.1.1', _not_ eşleşmelidir. Şikayet etmek isterseniz, '1.2.3' –

+0

@frb '1.1.1' hakkında şikâyetçi olmaz: link: http://regexpal.com/?flags=g®ex=(%3F!%5B%5Cd. % 5D * (% 5Cd)% 5B% 5Cd.% 5D *% 5C1)% 5E% 5B% 5Cd.% 5D% 2B% 24 & input = 1.1.1) ve Python'un neden farklı olması gerektiğini göremiyorum. –

+0

@frb'yi denemek gerekirse, geri dönüşler için bazı kaçış veya '\ 1' yerine' $ 1' gerekir? Ben bir regex hayranıyım, python-guru değil. –

0

:

from collections import Counter 

def unique(seq): 
    return any(x > 1 for x in Counter(seq).values()) 

Bu sadece dizeleri değil, herhangi bir dizi için çalışacaktır.

Ve şimdi sadece dizelere dönüştürmek istemediğimi farkettim ... emin değilim, ama cevabın kalmasına izin vereceğim.

+0

-1. Bu benim sorduğum şey değil. Lütfen sorumu tekrar okuyun. – pemistahl

İlgili konular