John Smith
John Smith

Reputation: 45

Checking if first digit in each element in list are the same

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

Answers (4)

Jongware
Jongware

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

cdlane
cdlane

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

jpp
jpp

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

Dani Mesejo
Dani Mesejo

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

Related Questions