【问题标题】:Checking if first digit in each element in list are the same检查列表中每个元素的第一个数字是否相同
【发布时间】:2018-10-29 00:54:56
【问题描述】:

如何检查列表中每个元素的第一个数字是否相同?

for i in range(0,len(lst)-1):
     if lst[i] == lst[i+1]:
          return True

我知道这会检查前面的数字是否等于列表中的下一个数字,但我只想关注第一个数字。

【问题讨论】:

  • 您需要检查多少位数?
  • 1,列表中每个元素的第一个数字

标签: python list


【解决方案1】:

您可以使用math.log10 和地板除法来计算第一位。然后使用all 和生成器表达式和zip 依次测试相邻元素:

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

有关此构造如何工作的说明,请参阅this related answer。您可以通过常规 for 循环应用相同的逻辑:

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

【讨论】:

    【解决方案2】:

    使用all() 作为数字的第一个字符的生成器:

    >>> l = [1, 10, 123]
    >>> all(str(x)[0] == str(l[0])[0] for x in l)
    True
    

    列表理解

    >>> [str(x)[0] for x in l]
    

    创建一个列表

    ['1', '1', '1']
    

    这听起来好像就足够了。但是all 处理boolean 值,并且字符串的布尔值始终为True,除非字符串为空。这意味着它还会将['1','2','3'] 视为True。您需要添加与常量值的比较——我从原始列表中选择了第一项:

    >>> [str(x)[0] == str(l[0])[0] for x in l]
    [True, True, True]
    

    [1,20,333] 之类的列表会显示

    ['1', '2', '3']
    

    [True, False, False]
    

    您也可以针对更多位数进行调整:

    >>> 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
    

    【讨论】:

    • 通过将参数调用到all() 一个列表理解,您正在低估(并且错误解释)这个解决方案。如果它是列表理解,这将是一个糟糕的解决方案,因为它会处理整个列表,然后将其传递,正如您的解释所说。但它是一个 generator 表达式,与all 结合使用时,它有一个很好的属性,即一旦遇到不匹配(如果有),它就会返回,而不是继续处理整个列表。虽然您可能会考虑使用for x in l[1:] 来避免不必要的比较。
    【解决方案3】:

    你可以这样做:

    lst = [12, 13, 14]
    
    
    def all_equals(l):
        return len(set(e[0] for e in  map(str, l))) == 1
    
    print all_equals(lst)
    

    输出

    True
    

    说明

    函数map(str, l) 将列表中的所有元素转换为字符串,然后使用(e[0] for e in map(str, l)) 使用生成器表达式获取所有元素的第一位。最后将生成器输入到 set 函数中,这将删除所有重复项,最后您必须检查集合的长度是否为 1,这意味着所有元素都是重复的。

    【讨论】:

    • 我对这样的解决方案的担忧是,如果我们有一千个元素列表,但前两个元素是[1, 2, ...],它仍然会将所有一千个元素处理成字符串并将第一个数字提取到决定结果。一个有效的解决方案应该在第一次冲突时返回 False 并忽略尚未看到的内容。
    【解决方案4】:

    对于这样的列表中的布尔谓词,您需要一个在发现冲突后立即返回False 的解决方案——转换整个列表只是为了找到第一个和第二项不匹配不是好的算法。这是一种方法:

    def all_same_first(a):
        return not a or all(map(lambda b, c=str(a[0])[0]: str(b)[0] == c, a[1:]))
    

    虽然乍一看这似乎违反了我上面所说的,map 函数是惰性的,因此只在需要时将其需要的东西交给all 函数,所以只要某些元素没有匹配第一个(初始数字)返回布尔结果,并且不处理列表的其余部分。

    回到原来的代码:

    这会检查之前的数字是否等于下一个 列表中的数字

    for i in range(0,len(lst)-1):
         if lst[i] == lst[i+1]:
              return True
    

    正如您所说,这不起作用。为了正常工作,它需要做:

    for i in range(0, len(lst) - 1):
         if lst[i] != lst[i + 1]:
              return False
    
    return True
    

    你看出区别了吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多