Reputation: 45
How would I check if the first digits in each element in a list are the same?
for i in range(0,len(lst)-1):
if lst[i] == lst[i+1]:
return True
I know that this checks for if the number before is equal to the next number in the list, but I just want to focus on the first digit.
Upvotes: 2
Views: 3833
Reputation: 22457
Use all()
as a generator for the first character(s) of your numbers:
>>> l = [1, 10, 123]
>>> all(str(x)[0] == str(l[0])[0] for x in l)
True
The list comprehension
>>> [str(x)[0] for x in l]
creates a list
['1', '1', '1']
which sounds as if this should be enough. But all
processes boolean values, and the boolean value of a string is always True
, except when the string is empty. That means that it would also consider ['1','2','3']
to be True
. You need to add a comparison against a constant value -- I picked the first item from the original list:
>>> [str(x)[0] == str(l[0])[0] for x in l]
[True, True, True]
whereas a list such as [1,20,333]
would show
['1', '2', '3']
and
[True, False, False]
You can adjust it for a larger numbers of digits as well:
>>> all(str(x)[:2] == str(l[0])[:2] for x in l)
False
>>> l = [12,123,1234]
>>> all(str(x)[:2] == str(l[0])[:2] for x in l)
True
Upvotes: 1
Reputation: 41872
For a boolean predicate on a list like this, you want a solution that returns False
as soon as a conflict is found -- solutions that convert the entire list just to find the first and second item didn't match aren't good algorithms. Here's one approach:
def all_same_first(a):
return not a or all(map(lambda b, c=str(a[0])[0]: str(b)[0] == c, a[1:]))
Although at first glance this might appear to violate what I said above, the map
function is lazy and so only hands the all
function what it needs as it needs it, so as soon as some element doesn't match the first (initial-digit-wise) the boolean result is returned and the rest of the list isn't processed.
Going back to your original code:
this checks for if the number before is equal to the next number in the list
for i in range(0,len(lst)-1):
if lst[i] == lst[i+1]:
return True
This doesn't work, as you claim. To work properly, it would need to do:
for i in range(0, len(lst) - 1):
if lst[i] != lst[i + 1]:
return False
return True
Do you see the difference?
Upvotes: 0
Reputation: 164643
You can use math.log10
and floor division to calculate the first digit. Then use all
with a generator expression and zip
to test adjacent elements sequentially:
from math import log10
def get_first(x):
return x // 10**int(log10(x))
L = [12341, 1765, 1342534, 176845, 1]
res = all(get_first(i) == get_first(j) for i, j in zip(L, L[1:])) # True
For an explanation of how this construct works, see this related answer. You can apply the same logic via a regular for
loop:
def check_first(L):
for i, j in zip(L, L[1:]):
if get_first(i) != get_first(j):
return False
return True
res = check_first(L) # True
Upvotes: 1
Reputation: 61910
You could do something like this:
lst = [12, 13, 14]
def all_equals(l):
return len(set(e[0] for e in map(str, l))) == 1
print all_equals(lst)
Output
True
Explanation
The function map(str, l)
converts all elements in the list to string then with (e[0] for e in map(str, l))
get the first digit of all the elements using a generator expression. Finally feed the generator into the set function this will remove all duplicates, finally you have to check if the length of the set is 1, meaning that all elements were duplicates.
Upvotes: 0