【问题标题】:Eliminating duplicate entries in a two dimensional array in python 3在python 3中消除二维数组中的重复条目
【发布时间】:2018-07-31 05:21:56
【问题描述】:

我不确定这是否是解决问题的最佳方法 - 我是新手,所以我会给你一些背景知识:

我设法创建了一个程序,它可以为我抓取一些网站并根据特定标准向我返回天气报告。其中一些非常相似,如果不相同的话,滚动浏览同一地区的十几个报告仍然很乏味。更有用的是,如果我可以将这些报告合并为一个,同时添加每个报告的标题。

到目前为止,我的程序所做的是将每个报告分解为:

  • 标题
  • 警告类型
  • 正文

这些被推入一个更大的数组,其中一维的长度为 [x],另一维的长度为 [3]。

我的想法是我是否可以遍历数组并比较每个数组的正文。如果正文不同,它会跳过它,但如果它们相同,我的程序可以将标题添加到下一个,然后完全删除该条目。

结果并不理想。我已经尝试了几种不同的方法,结果好坏参半,但这是我目前所拥有的:

#Overall array as list
practice_array = []

#Sub lists
first_array = ["header 1", "warning", "body"]
second_array = ["header 2", "warning", "body"]
third_array = ["header 3", "warning", "body"]
fourth_array = ["header 4", "warning", "body"]
fifth_array = ["header 5", "warning", "body"]

#Values of practice_array
practice_array = [first_array, second_array, third_array, fourth_array,
fifth_array]

#Length of the loop
length = len(practice_array)

#Loop starts with the first item in the list 
for x in range(0, length):

    #The second loop starts with the next so it has something to compare
    for y in range(1, length):

        #If the body texts are the same then...
        if practice_array[x][2] == practice_array[y][2] :

             #Add the header to the other header
             practice_array[y][0] += (' ' + practice_array[x][0])

             #Delete the first item
             del practice_array[x]

             #Print for me to see
             print(practice_array[y][0])

IndexError: 列表索引超出范围

【问题讨论】:

  • 如果你给出一个示例输出,也就是你希望输出在结构上看起来像什么,有人可以给你写一个列表理解,它将在一行中处理这个问题。事实上,很难掌握你的最终目标是什么。
  • 阅读代码,您会收到索引错误,因为您正在删除数组中的元素,因此数组长度将不再是 5。因此,当您尝试访问元素 practice_array[4][2] 时,它将失败,因为您已经删除了一个元素
  • 使用上面它看起来像: practice_array[0][0] "header 1 header 2 header 3 header 4 header 5" practice_array[0][1] "warning" practice_array[0 ][2] “身体”
  • 卡洛斯文,我也是这么想的。我不知道如何解决这个问题,我认为我没有以正确的方式解决这个问题。
  • @MattK 一个简单的解决方案是使用另一种数据结构来创建您的结果,如果您的身体是您的标识符,python dict 可以完美匹配。我会尝试写一个例子

标签: python arrays python-3.6 nested-lists


【解决方案1】:

您收到索引错误是因为您在循环遍历其内容时更改了“practice_array”的大小,但您可能已经知道这一点。

要利用内置函数的速度,您可以使用将 practice_array 转换为集合,然后使用new_array_1 = list(set(practice_array)) 转换回列表。这假设您不关心列表的顺序,这只会消除相同的数组。

无论是否使用set() 转换,如果未找到列表的“body”元素,您都可以在新列表中累积具有唯一“body”元素(无论标题和警告是否相同)的数组在一个累积“body”元素的列表中。

new_array_2 = []
body_els = []

for el in new_array_1:
    if el[2] in body_els:
        pass
    else:
        new_array_2.append(el)
        body_els.append(el[2])

在循环结束时,new_array_2 将是具有唯一主体元素的数组列表。

【讨论】:

    【解决方案2】:

    使用字典来构造结果很容易实现,并且得到 O(n) 时间复杂度。 我希望我能正确理解你想要达到的目标。

    practice_dict = {}
    for p in practice_array:
        body = p[2]
        if body in practice_dict:
            practice_dict[body][0] += (' ' + p[0])
        else:
            practice_dict[body] = p
    
    print(practice_dict)
    

    输出:

    {'body': ['header 1 header 2 header 3 header 4 header 5', 'warning', 'body']}
    

    你也可以使用列表,但不太方便

    【讨论】:

      【解决方案3】:

      IndexError 是因为您在删除并尝试访问后迭代中超出范围的元素时更改了列表大小。

      这是我认为您想要做的一种可能的解决方案

      # Get all different body values
      unique_body = set([i[2] for i in practice_array])
      
      result = []
      # Iterate over body values
      for body in unique_body:
          # Get all entries have the same body value
          matching_entries = [i for i in practice_array if i[2] == body]
      
          # Join the headers
          header = ' '.join([i[0] for i in matching_entries])
      
          # Make a new entry and append it to a result list
          merged_entry = [header, matching_entries[0][1], body]
          result.append(merged_entry)
      

      【讨论】:

        【解决方案4】:
        for i in range(len(practice_array)):
            if len(practice_array[i]) == 0:
                    continue
            for j in range(1, len(practice_array)):
                if len(practice_array[j]) == 0:
                    continue
                if i != j and practice_array[i][2] == practice_array[j][2]:
                    practice_array[i][0] += " {}".format(practice_array[j][0])
                    practice_array[j] = []
        practice_array = list(filter(lambda x: len(x) > 0, practice_array))
        

        你应该这样做。您绝不能从您正在处理的列表中删除项目,更不用说将其长度存储在变量中并将其用作条件(当实际长度减少时)。比较后,只需将每个内部列表替换为相同的 body 并使用不会通过过滤条件的简单内容,因此您可以通过仅选择您需要的项目来更新结果列表(如这里:我们用相同的项目替换列表body 带有空列表,以便我们稍后过滤掉它们。

        【讨论】:

          【解决方案5】:

          您的算法正在检查每个条目,并将其与其他每个条目进行比较。这将为您提供 O(n^2) 性能。您可以通过首先对文本字段进行排序来将其降低到 O(n) 性能。然后你只需要比较每对连续的条目。

          【讨论】:

          • 正确地说,如果您在 Python 中对列表进行排序,您将得到 O(n log n) wiki.python.org/moin/TimeComplexity
          • 这超出了我现在的能力。我只需要它工作,然后也许我会考虑优化它。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-14
          • 2012-01-21
          • 2014-04-29
          • 2017-05-07
          • 1970-01-01
          相关资源
          最近更新 更多