Reputation: 9584
You have a list of numbers and you want to filter out those numbers that contain unique digits, i.e. each digit may only occur once in the number.
Positive examples:
Negative examples:
How would you do that? My own idea is to convert each number to a string and then check whether the size of the set made out of the string's characters is equal to the length of the string. Something like that:
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
Is there a way to do it without converting the integers to strings first?
Upvotes: 9
Views: 2973
Reputation: 27277
If you want a regex-based solution, consider the following regex :
(?![\d.]*([\d.])[\d.]*\1)^[\d.]+$
That is, match a sequence of digits and periods if there are no duplicate digits and there is not a duplicate decimal point.
Update (thanks @frb): the correct way to write this in Python is
re.match(r"(?![\d.]*([\d.])[\d.]*\1)^[\d.]+$",str_number).group(0)
Upvotes: 3
Reputation: 34145
Using collections.Counter:
from collections import Counter
def unique(seq):
return any(x > 1 for x in Counter(seq).values())
This will work for any sequence, not only strings.
And only now I noticed that you didn't want to convert to strings... not sure why, but I'll let the answer stay.
Upvotes: 1
Reputation: 879391
Is there a way to do it without converting the integers to strings first and then convert them back?
Yes, you could use divmod
to find the digits base 10, but this is not faster than the method you posted:
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
Upvotes: 9
Reputation: 566
Try:
def predicate(n):
s = repr(n)
return len(s) == len(set(s))
filtered_numbers = [ n for n in numbers if predicate(n) ]
or, if you prefer filter function:
filtered_numbers = filter(predicate, numbers)
or:
filtered_numbers = filter(lambda n: len(repr(n)) == len(set(repr(n))), numbers)
Upvotes: 5