判断一个列表是另外一个列表的子列表

博客先指出之前代码仅适合特定要求,项目要求判断如[1,2,3]是否为[1,2,3,4]等列表的子序列列表,随后表示接下来的代码可用于判断一个列表是否为另一个列表的子列表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

pre_seq_list = [[17, 37, 38, 37, 38, 37, 38, 37], [17, 37, 38, 37, 38, 37, 37], [17, 37, 38, 37, 38, 38, 37],

  [17, 37, 38, 37, 37, 38, 37, 37], [17, 37, 38, 37, 37, 38, ], [17, 37, 38, 37, 37, 38, 38, 37],
  [17, 37, 38, 37, 37, 37, 37, 38, 37], [17, 37, 38, 37, 37, 37, 37, 37], [17, 37, 38, 37, 37, ],
      [17, 37, 38, 37, 38, 37, 38, 37, 39], [17, 37, 38, 37, 37, 37, 37, 38, 37, 39]]
"""把列表组合按照大小排序"""
num_seq = len(pre_seq_list)
order_list = []
while len(order_list) < num_seq:
    m = pre_seq_list[0]
    k=0
    for i in range(len(pre_seq_list)):
        if len(pre_seq_list[i]) <= len(m):
            m = pre_seq_list[i]
            k = i

    order_list.append(pre_seq_list[k])
    del pre_seq_list[k]
# print(order_list)


"""定义函数判断l1是不是l2的子列表"""
def is_l1_in_l2(l1, l2):  # 如果列表l1是列表l2的子序列,则返回1
    cursor = 0  # 记录匹配到item条目的位置,下一个条目匹配从此位置开始
    num_item = 0  # 记录匹配列表l1条目的值
    for item in l1:
        if cursor < len(l2):
            for j in range(cursor, len(l2)):
                if l2[j] == item:
                    cursor = j+1
                    num_item = num_item+1
                    break
    if num_item == len(l1):  # 如果能l1是l2的子序列,则返回true
        return 1
    else:  # 返回false
        return 0


while i < len(order_list):
    for j in range(i+1, len(order_list)):
        if is_l1_in_l2(order_list[i], order_list[j]):
            del order_list[i]
            break
    i = i+1

print(len(order_list))

当然,以上代码只适合我的要求,项目要求[1,2,3]是[1,2,3,4] , [1,3,2,3,4,] , [1,1,2,,2,3,3,], [1,32,4,4,65,2,2,4,3]等列表的子序列列表。

接下来的代码才是实实在在的判断一个列表是另外一个列表的子列表:

def is_l1_in_l2(l1, l2):  # 如果列表l1是列表l2的子序列,则返回1
    
    flag = 0  # 如果匹配成功这置为1
    
    for j in range(len(l2)):
        child_list = l2[i:i+len(l1)]  # 截取与l1等长的序列
        if child_list == l1:
            flag =1
            break  # 找到匹配项,则跳出循环,结束函数
    return flag
  

 

<think>我们有两个问题需要解决:1.如何判断一个列表的维度(即嵌套深度)?2.如何解决与`pd.isna`相关的`ValueError`(当应用于多维数组或列表时)?我们先解决第一个问题:如何判断一个列表的维度(嵌套深度)?思路:递归地检查列表是否包含子列表。如果当前对象是一个列表,那么其维度就是1+其元素的最大维度(递归计算)。如果当前对象不是列表,则维度为0。但是注意:用户提到的是“多维列表”,但实际上Python中的列表可以嵌套形成多维,但是每一层嵌套的列表长度不一定相同(不一定是矩形数组)。然后解决第二个问题:当使用`pd.isna`检查一个非一维结构(比如二维列表)时,会返回一个布尔值数组,此时不能直接用在`if`条件中,因为会产生歧义(多个布尔值)。我们需要使用`.any()`或`.all()`来消除歧义。然而,`pd.isna`设计用于处理一维的Series和二维的DataFrame,以及标量。如果我们传入一个嵌套列表(非矩形)或者多维数组(numpy数组),它可能会返回一个数组(array-like)对象,这样在`if`语句中就会出错。因此,我们需要:-首先确定输入数据的维度,以便决定如何处理。-然后根据维度和我们的需求(是检查是否有任意缺失值,还是全部是缺失值)来使用`.any()`或`.all()`。结合引用[^1]中提到的`.empty`属性(虽然这里不是直接相关,但我们可以借鉴思路:明确检查条件),以及引用[^2]中元素级比较(返回布尔数组),我们可以这样处理:步骤:1.判断输入数据的维度(嵌套深度)。2.根据维度决定如何处理`pd.isna`的返回结果。但是,注意:`pd.isna`可以处理多维数组(numpy数组)吗?实际上,`pd.isna`可以处理numpy数组并返回一个布尔数组,其形状与输入相同。但是,对于不规则的嵌套列表,它可能不会正常工作(因为不是矩形结构)。因此,我们可能需要先将不规则嵌套列表转换为numpy数组(但这是不可能的,因为numpy要求矩形结构)或者使用其他方法。因此,我们分情况讨论:情况一:一维列表(或Series)——可以直接使用`pd.isna`,然后配合`.any()`或`.all()`。情况二:二维矩形列表(或DataFrame)——同样可以使用`pd.isna`,然后使用`.any()`两次(因为返回的是二维布尔数组)或使用`.any()`一次并指定轴。情况三:非矩形嵌套列表(不规则)——不能直接使用`pd.isna`,可能需要递归处理。但为了简化,我们假设用户处理的是矩形结构(即每个子列表长度相同),这样我们可以将其转化为numpy数组或者DataFrame。如果是不规则结构,则递归处理每一层。然而,`pd.isna`本身不支持非矩形结构。所以,对于不规则嵌套列表,我们可能需要自己编写递归函数来检查缺失值。所以,我们将问题拆分为:A.如何检测一个嵌套列表的维度(假设是矩形结构)?B.对于给定维度的矩形结构,如何正确使用`pd.isna`并避免`ValueError`?C.对于非矩形结构(不规则)如何处理?由于用户的问题中并没有明确数据是矩形还是不规则,我们提供两种方案。首先,我们解决维度检测的问题:方法:写一个递归函数,计算嵌套列表的深度。例如:```pythondefget_depth(lst):ifnotisinstance(lst,list):return0elifnotlst:#空列表return1else:return1+max(get_depth(item)foriteminlst)```但是,这个函数对于不规则嵌套是有效的,但是对于矩形结构(如二维数组)也是有效的。接下来,我们考虑如何处理`pd.isna`的调用:对于一维和二维矩形结构,我们可以使用`pd.isna`,然后通过`any()`来检查是否存在缺失值(或`all()`来检查是否全部是缺失值)。注意,二维结构需要两次`any()`(第一次按行或列聚合,第二次再聚合为标量)或者使用`np.any()`。对于不规则结构,我们可能需要递归地应用`pd.isna`(但注意,`pd.isna`对于单个元素也是有效的,比如标量)。因此,我们可以写一个函数来统一处理:```pythonimportpandasaspdimportnumpyasnpdefhas_missing(value):#先判断是不是可以转换为矩形的结构(即规则的多维列表)try:#尝试转换为numpy数组(要求矩形)arr=np.array(value)#如果成功,则使用pd.isna并检查anyreturnpd.isna(arr).any()except:#转换失败,说明是不规则结构,使用递归ifisinstance(value,list):#对于列表,递归检查每个元素returnany(has_missing(item)foriteminvalue)else:#单个元素returnpd.isna(value)```但是注意,上面的递归可能会漏掉一些情况,比如列表中的元素不是标量而是可转换为数组的对象(比如元组)。而且,使用异常来控制流程不是最佳实践。另一种思路:根据我们之前计算的深度来分派处理方式。如果深度为1(一维列表),则直接用`pd.isna`然后`any()`。深度为2,我们假设是矩形(每个子列表长度相同),然后转换为数组处理。深度大于2,我们可以递归或者转换为更高维数组(如果规则的话),否则递归处理。但是,我们可能无法简单区分规则与不规则。所以,我们提供一个较为通用的方法,优先尝试用numpy数组转换,如果转换成功(规则结构)则用数组方式处理,如果不成功(不规则)则递归处理。但是,由于不规则嵌套列表无法转换为numpy数组,所以我们在转换失败时采用递归。下面我们实现一个函数,用于检查任意结构(标量,一维列表,二维矩形列表,不规则嵌套列表)中是否存在缺失值:```pythonimportnumpyasnpimportpandasaspddefhas_any_missing(obj):#尝试将对象转换为numpy数组(针对规则结构)try:arr=np.array(obj)#如果成功,则使用pd.isna并检查整个数组中是否存在缺失值returnpd.isna(arr).any()exceptValueError:#如果转换失败,说明可能是不规则结构pass#处理不规则结构或标量ifnotisinstance(obj,list):#如果是单个元素returnpd.isna(obj)else:#如果是列表(可能是嵌套的),递归检查每个元素foriteminobj:ifhas_any_missing(item):returnTruereturnFalse```注意:上面的递归在遇到非常大的嵌套结构时可能会导致递归深度问题,但这是一个通用解决方案。另外,我们还可以用循环替代递归来避免递归深度问题,但处理嵌套结构递归比较直观。现在,针对用户遇到的错误:在多维数组上直接使用`ifnotpd.isna(x)`,我们应该建议使用`.any()`或`.all()`来聚合结果,而不是直接用于条件判断。所以,总结解决方案:1.对于一维数组(列表或Series),使用:`ifpd.isna(x).any():`或`ifpd.isna(x).all():`2.对于二维数组(DataFrame或二维numpy数组),使用:`ifpd.isna(x).any().any():`(检查整个DataFrame是否有任何缺失值)或`ifpd.isna(x).all().all():`(检查是否全部是缺失值)3.对于更高维或嵌套不规则结构,使用我们上面写的`has_any_missing`函数。最后,我们回答用户的问题:用户的问题有两个部分:-如何判断列表的维度(嵌套深度)?-如何解决`pd.isna`在多维结构上的`ValueError`?我们分别给出示例代码。第一部分:维度检测函数```pythondefget_depth(lst):"""计算嵌套列表的深度"""ifnotisinstance(lst,list):return0#对于空列表,深度为1ifnotlst:return1#递归计算子元素的最大深度,然后加1return1+max(get_depth(item)foriteminlst)#示例:list_1d=[1,2,3]list_2d=[[1,2],[3,4]]list_irregular=[[1,[2,3]],[4,[5,6,[7]]]]print(get_depth(list_1d))#1print(get_depth(list_2d))#2print(get_depth(list_irregular))#3```第二部分:避免`ValueError`,使用聚合函数或自定义函数示例1:处理一维列表```pythonimportpandasaspdlst=[1,2,None,4]#错误写法:ifpd.isna(lst):...#将导致ValueError#正确写法:ifpd.isna(lst).any():print("存在缺失值")```示例2:处理二维矩形列表```pythonlst_2d=[[1,2],[None,4]]#转换为DataFrame或numpy数组后处理df=pd.DataFrame(lst_2d)ifdf.isna().any().any():#或者使用np.any(pd.isna(lst_2d))print("存在缺失值")```示例3:处理不规则嵌套列表(使用自定义函数`has_any_missing`)```python#使用前面定义的has_any_missing函数ifhas_any_missing(list_irregular):print("存在缺失值")```这样,我们就可以处理任意维度的列表,并避免`ValueError`。根据引用[^3],我们不推荐使用`.values`,所以对于DataFrame,我们使用`df.isna()`而不是`pd.isna(df.values)`。另外,引用[^1]提到用`.empty`检查是否为空,这和我们检查缺失值不是同一个问题,但要注意,如果整个结构是空的,那么它也不包含缺失值?但空结构可能有不同含义,需要根据业务逻辑处理。最后,如果用户正在处理NumPy数组,也可以直接使用`np.isnan`,但注意`np.isnan`只支持数值类型,而`pd.isna`还支持字符串和datetime等类型。因此,我们推荐使用`pd.isna`因为它更通用。生成的相关问题:§§相关问题§§1.如何判断一个嵌套列表是否为矩形(即每个子列表长度相同)?2.在Pandas中,如何检查整个DataFrame是否存在缺失值?3.如何递归展平一个不规则的嵌套列表?4.如何在避免递归深度限制的情况下处理超大型嵌套结构?</think> ### 解决多维列表判断与 `pd.isna()` 的 ValueError 问题 #### 一、问题分析 当您尝试用 `if not pd.isna(x)` 判断多维列表(嵌套列表)时,会出现 `ValueError` 错误: ```python ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() ``` 原因在于: 1. `pd.isna(x)` 对多维列表返回嵌套布尔数组(如 `[[True, False], [False, True]]`) 2. Python 无法自动判断多值条件的真假(需要明确用 `.any()` 或 `.all()`) 3. 嵌套列表的维度不明确,需先检测维度再处理 --- #### 二、解决方案:分步处理多维列表 ##### 步骤 1:检测列表维度(嵌套深度) 使用递归函数计算最大嵌套深度: ```python def get_dimension(lst): """计算列表的嵌套深度(维度)""" if not isinstance(lst, list): return 0 # 非列表对象维度为0 if not lst: return 1 # 空列表维度为1 return 1 + max(get_dimension(item) for item in lst) # 测试用例 print(get_dimension([1, 2, 3])) # 输出:1 (一维) print(get_dimension([[1, 2], [3, 4]])) # 输出:2 (二维) print(get_dimension([[[1]]])) # 输出:3 (三维) ``` ##### 步骤 2:按维度处理 `pd.isna()` 根据维度选择聚合方式: | 维度 | 判断逻辑 | 代码示例 | |------|------------------------------|-----------------------------------| | 一维 | 直接使用 `.any()`/`.all()` | `pd.isna(lst).any()` | | 二维 | 双重聚合 | `pd.isna(lst).any().any()` | | 高维 | 递归处理 | 见下方通用处理函数 | **通用处理函数**: ```python import pandas as pd import numpy as np def has_any_na(data): """检查任意维度数据中是否存在缺失值""" if not isinstance(data, list) and not isinstance(data, np.ndarray): return pd.isna(data) # 处理标量 # 将列表转为 NumPy 数组统一处理 arr = np.array(data, dtype=object) if isinstance(data, list) else data # 使用 np.any 自动处理多维数组 return np.any(pd.isna(arr)) # 测试用例 print(has_any_na([[1, None], [3, 4]])) # 输出:True print(has_any_na([[1, 2], [3, 4]])) # 输出:False ``` ##### 步骤 3:正确替换错误写法 原错误代码: ```python if not pd.isna(x): # 会引发 ValueError ... ``` 修正为: ```python if not has_any_na(x): # 使用安全检测函数 print("无缺失值") ``` --- #### 三、关键注意事项 1. **维度检测必要性** 对嵌套列表需先明确维度: ```python # 不规则嵌套列表示例(非矩形结构) irregular = [[1, 2], [3, [4, None]]] print(get_dimension(irregular)) # 输出:3 ``` 此时需用递归或 `np.ravel()` 展平处理[^1][^2] 2. **`.any()` vs `.all()`** - `.any()`:存在即真($\exists x,\ \text{isna}(x)$) - `.all()`:全部为真($\forall x,\ \text{isna}(x)$) ```python data = [[1, None], [None, 4]] print(pd.isna(data).any().any()) # True(有至少1个NA) print(pd.isna(data).all().all()) # False(非全部是NA) ``` 3. **Pandas/NumPy 最佳实践** - 用 `pd.isna()` 替代 `np.isnan()`(支持字符串等类型) - 优先将列表转为 NumPy 数组处理[^3] - 避免直接使用 `.values`(推荐 `to_numpy()`[^3]) --- ### 常见场景解决方案 #### 场景 1:检查二维数据是否存在 NA ```python # 创建测试数据(含None和NaN) data_2d = [[1, None], [3, float("nan")]] # 方法1:双重any聚合 has_na = pd.isna(data_2d).any().any() # 方法2:展平后判断 flattened = [item for sublist in data_2d for item in sublist] has_na = pd.isna(flattened).any() ``` #### 场景 2:处理非矩形嵌套结构 ```python # 不规则嵌套列表 irregular = [1, [2, None, [3, float("nan")]]] # 递归展平函数 def flatten(lst): for item in lst: if isinstance(item, list): yield from flatten(item) else: yield item has_na = pd.isna(list(flatten(irregular))).any() ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值