【问题标题】:Iterating nested list, comparing to other list items by looking right instead of down迭代嵌套列表,通过向右而不是向下看与其他列表项进行比较
【发布时间】:2019-07-03 19:51:55
【问题描述】:

我有下面的嵌套列表称为row_list

[
    [{
        'text': 'Page 1, col 1.',
        'top': Decimal('83.640')    
    }],
    [{
        'text': 'Page 1, col 2.',
        'top': Decimal('112.920')
    }],
    [{
        'text': 'Page 1, col 3',
        'top': Decimal('127.560'),
    }]
]

现在,我正在尝试迭代此列表列表。

但是,当我迭代时,我想获取 n 列表中的每个项目,并向右“看” - 这意味着我想检查 以下 列表(除非它是最后一个列表),相同的n 项目的值。

例如,对于我的列表的第一次迭代,如下:

[{
   'text': 'Page 1, col 1.',
   'top': Decimal('83.640')    
}]

这里我想检查其他列表中其他nitem 的top 值。如果该最高值相同(或在 10 的容差范围内),我想在同一 n 位置添加一个新项目 - 但在另一个列表中。

所以按照上面的例子,83.640 的顶层不在其他两个列表的接受范围内,所以我们应该为每个列表添加一个项目:

[
    [{
        'text': 'Page 1, col 1.',
        'top': Decimal('83.640')    
    }],
    [{
        'text': '', #added item
        'top': Decimal('83.640')
    },{
        'text': 'Page 1, col 2.',
        'top': Decimal('112.920')
    }],
    [{
        'text': '', #added item
        'top': Decimal('83.640')
    },{
        'text': 'Page 1, col 3',
        'top': Decimal('127.560'),
    }]
]

我试图弄清楚如何从左到右而不是从上到下查看列表。这是我目前所拥有的:

for col_no, col in enumerate(row_list):
    #Don't compare the last list, as there are no more lists to compare to.
    if col != row_list[-1]:
        for line in col:
            currentTopValue = line['top']
            nextColValue = row_list[col_no + 1][0]['top']
            if abs(currentTopValue - nextColValue) >= float(10):
                row_list.insert(0, [{'text': '', 'top': currentTopValue}])

如您所见,以上内容是相当静态的(硬编码索引)。行列表可以在每个列表中包含许多项。

由于某种原因,当我执行代码时,它没有运行(似乎它挂了 - 可能是瓶颈?)

谁能指引我正确的方向?

【问题讨论】:

    标签: python python-3.x python-3.7


    【解决方案1】:

    而不是这个 if 语句:

    if col != row_list[-1]:
    

    尝试明智地构建循环:

    for col_no, col in enumerate(row_list[:-1]):
    

    并且您的代码不起作用,因为您在 for 循环期间插入了 row_list 新元素。 那里:

                row_list.insert(0, [{'text': '', 'top': currentTopValue}])
    

    好的方法是创建temp_row_list = [] 并将这些数据插入其中。

    它应该可以工作,检查一下:

    temp_row_list = []
    for col_no, col in enumerate(row_list[:-1]):
        for line in col:
            currentTopValue = line['top']
            nextColValue = row_list[col_no + 1][0]['top']
            if abs(currentTopValue - nextColValue) >= float(10):
                temp_row_list.append([{'text': '', 'top': currentTopValue}])
    

    【讨论】:

    • 我对@9​​87654327@ 部分有点不确定。这样做不是让我们从最后一项开始吗?我只想检查前两个列表。我需要将值附加/添加到我的row_list - 那么如何将{'text': '', 'top': currentTopValue} 插入nth 位置row_list
    • 不,这是list_slices,什么是避免最后一个元素。检查我为您发送的这个示例,然后尝试使用 pythontutor.com 或一些类似的可视化引擎进行调试:)。如果您以这种方式填写列表,则应按开始顺序对它们进行排序,要反转您可以使用该结构:[::-1]
    • 啊,明白了!但仍然 - 我如何将实际的 nth 项目附加到 row_list?现在,他们被添加到temp_row_list
    • 通过索引分配你可以替换列表中的值,如果你问这个:)。例如:row_list[col_no][0] = {'text':'', 'top': currentTopValue} 或 ingore secound index,如果你想得到 dicts 列表。如果我理解错误,请纠正我:)
    • 但是值不应该被替换,应该在列表中插入一个新项目(但在列表中的nth位置)
    【解决方案2】:

    因为我们正在修改添加dicts的子列表,所以我们要追踪谁是原始元素;因为您将'top' 属性设置为'',所以我们可以搜索子列表中包含一些文本的第一个元素。

    def get_elem_for_sublist(sublist: list):
        for elem in sublist:  # dict
            if elem['text'] != '':
                return elem
        return None
    

    然后我们可以循环遍历具有指定容差的列表。我们可以使用当前子列表的计数器,并在while 循环结束时将其增加1。

    通过枚举获取索引和子列表,我们可以检查if counter_sublist == idx,得到value_to_compare,或者valuevalue_to_compare之间的当前差异大于tolerance

    def add_elems(row_list: list, tolerance: Decimal):
        counter_sublist = 0
    
        while counter_sublist < len(row_list) - 1:
            for idx, sublist in enumerate(row_list[counter_sublist:]):
                actual_idx = idx + counter_sublist
    
                value = get_elem_for_sublist(sublist)['top']  # decimal
    
                if actual_idx == counter_sublist:  # get value to compare
                    value_to_compare = value
                elif abs(value - value_to_compare) >= tolerance:  # add dict into sublist
                    dict_to_add = {
                        'text': '',
                        'top': value_to_compare
                    }
                    sublist.insert(counter_sublist, dict_to_add)
            counter_sublist += 1
    
        return row_list
    

    输出是

    [
        {'text': 'Page 1, col 1.', 'top': Decimal('83.640')}
    ],
    [
        {'text': '', 'top': Decimal('83.640')}, 
        {'text': 'Page 1, col 2.', 'top': Decimal('112.920')}
    ],
    [
        {'text': '', 'top': Decimal('83.640')}, 
        {'text': '', 'top': Decimal('112.920')}, 
        {'text': 'Page 1, col 3', 'top': Decimal('127.560')}
    ]
    

    【讨论】:

    • 但这不会在nth 项中插入'text': '', 'top': [...]。它附加到列表中。正如您在示例中的第二个列表中看到的那样,它被添加到列表的末尾,而它应该位于顶部(因为在第一个列表中,对于第一项,top 值不等于(或在第二个(或第三个)列表中的第一个值的公差内。
    • 所以第一个项目应该在第一个位置,第二个在第二个位置,等等?如果是这样,这个简单的编辑将为您完成工作(而不是 append 我在 counter_sublist 位置使用 insert
    猜你喜欢
    • 1970-01-01
    • 2022-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    相关资源
    最近更新 更多