9

你有一个数字列表,你想过滤掉那些包含唯一数字的数字,即每个数字在数字中只能出现一次。

正面例子:

  • 985
  • 58293.6
  • 0.1246

负面例子:

  • 9585(5 出现两次)
  • 58293.666(6出现3次)
  • 0.12461(1 出现两次)

你会怎么做?我自己的想法是将每个数字转换为字符串,然后检查由字符串字符组成的集合的大小是否等于字符串的长度。像这样的东西:

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

有没有办法在不先将整数转换为字符串的情况下做到这一点?

4

4 回答 4

9

有没有办法在不先将整数转换为字符串然后再将它们转换回来的情况下做到这一点?

是的,您可以divmod用来查找以 10 为底的数字,但这并不比您发布的方法快:

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
于 2013-01-14T11:07:36.957 回答
5

尝试:

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

或者,如果您更喜欢过滤功能:

filtered_numbers = filter(predicate, numbers)

或者:

filtered_numbers = filter(lambda n: len(repr(n)) == len(set(repr(n))), numbers)
于 2013-01-14T11:00:12.050 回答
3

如果您想要基于正则表达式的解决方案,请考虑以下正则表达式:

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

也就是说,如果没有重复的数字并且没有重复的小数点,则匹配一系列数字和句点。

更新(感谢@frb):用 Python 写这个的正确方法是

re.match(r"(?![\d.]*([\d.])[\d.]*\1)^[\d.]+$",str_number).group(0)
于 2013-01-14T11:03:03.813 回答
1

使用 collections.Counter:

from collections import Counter

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

这适用于任何序列,而不仅仅是字符串。

直到现在我才注意到你不想转换为字符串......不知道为什么,但我会让答案留下来。

于 2013-01-14T11:08:42.943 回答