【问题标题】:Sorting through a nested list对嵌套列表进行排序
【发布时间】:2013-02-06 07:06:34
【问题描述】:

我有一个描述层次结构的列表,如下所示:

[obj1, obj2, [child1, child2, [gchild1, gchild2]] onemoreobject]

其中,child1(和其他)是 obj2 的孩子,而 gchild1 和 2 是孩子 2 的孩子。

每个对象都有date 之类的属性,例如,我想根据这些属性对它们进行排序。在常规列表中,我会这样:

sorted(obj_list, key=attrgetter('date'))

在这种情况下,尽管如此,该方法不起作用,因为列表没有date 属性......即使它有,如果它的属性与其父级不同,那么层次顺序就会被破坏。在 python 中是否有一种简单而优雅的方法来做到这一点?

【问题讨论】:

  • 这看起来将是一个完美的树结构数据集。
  • 你能提供想要的输出吗?您想在保持层次结构的同时按字典顺序对列表进行排序吗?即,[obj2, obj1, [child1, child2, [gchild1, gchild2]] onemoreobject] 将排序为 [obj1, [child1, child2, [gchild1, gchild2]], obj2, onemoreobject]?
  • 如前所述,所需的输出将取决于名为date 的对象属性。如果日期以这种方式排列,您的示例将是有效的,但我绝不打算根据对象名称进行排序。因此,如果obj1.date 排在第二位,obj2.date 排在第一位,则列表的这一部分应如下所示:[obj2, [child1, child2, [gchild1, gchild2]], obj1]

标签: python list nested


【解决方案1】:

我认为您只需将密钥放入 sort(key=None) 函数中即可。我用字符串测试了它,它似乎工作。我不确定 onemoreobject 的结构。这以 obj1 和 obj2 排序到开头。我认为 onemoreobject 可能代表一个新的层次结构,因此我将每个层次结构都包含在一个列表中,以将类似的对象放在一起。

def embededsort(alist):
  islist = False
  temp = []
  for index, obj in enumerate(alist):
    if isinstance(obj,list):
      islist = True
      embededsort(obj)
      temp.append((index,obj))
  if islist:
    for lists in reversed(temp):
      del alist[lists[0]]
    alist.sort(key=None)
    for lists in temp:
      alist.append(lists[1])
  else:
    alist.sort(key=None)
  return alist

>>>l=[['obj2', 'obj1', ['child2', 'child1', ['gchild2', 'gchild1']]], ['obj22', 'obj21', ['child22', 'child21', ['gchild22', 'gchild21']]]]  
>>>print(embededsort(l))
[['obj1', 'obj2', ['child1', 'child2', ['gchild1', 'gchild2']]], ['obj21', 'obj22', ['child21', 'child22', ['gchild21', 'gchild22']]]]

【讨论】:

    【解决方案2】:

    这是一个使用 Python 提供的多态性的 QuickSort 算法的实现。它应该适用于整数、浮点数、列表、嵌套列表、元组甚至字典

    def qsort(list):
        if not list: return []
        first   = list[0]
        lesser  = filter( lambda x: x <  first, list[1:] )
        greater = filter( lambda x: x >= first, list[1:] )
        return qsort(lesser) + [first] + qsort(greater)
    

    【讨论】:

    • 在平面列表上工作,但在我的嵌套列表上仍然得到:AttributeError: 'list' object has no attribute 'date'
    【解决方案3】:

    感谢您的回答,因为他们给了我很多想法,以及可以学习的新东西。最终的代码,看起来像这样。不像我想象的那样简洁优雅,但很有效:

    def sort_by_date(element_list):
        last_item = None
        sorted_list = []
        for item in element_list:
            #if item is a list recurse and store it right below last item (parent)
            if type(item) == list:
                if last_comparisson:
                    if last_comparisson == 'greater':
                        sorted_list.append(sort_by_date(item))
                    else:
                        sorted_list.insert(1, sort_by_date(item))
            #if not a list check if it is greater or smaller then last comparisson
            else:
                if last_item == None or item.date > last_item:
                    last_comparisson = 'greater'
                    sorted_list.append(item)
                else:
                    last_comparisson = 'smaller'
                    sorted_list.insert(0, item)
                last_item = item.date
        return(sorted_list)
    

    【讨论】:

      【解决方案4】:

      如果您想对节点的所有子节点进行排序而不考虑那些不是兄弟节点的节点,请使用树结构:

      class Tree:
          def __init__ (self, payload):
              self.payload = payload
              self.__children = []
      
          def __iadd__ (self, child):
              self.__children.append (child)
              return self
      
          def sort (self, attr):
              self.__children = sorted (self.__children, key = lambda x: getattr (x.payload, attr) )
              for child in self.__children: child.sort (attr)
      
          def __repr__ (self):
              return '{}: {}'.format (self.payload, self.__children)
      

      【讨论】:

      • 我认为这个答案会在这部分问题上绊倒:“如果它的属性与其父级不同,那么层次顺序就会被破坏”。
      • 我不明白这部分问题。你能给我解释一下这是什么意思吗?
      • 他是不是要根据一个属性对每个节点的子节点进行排序,而不考虑其余节点?
      • 由于 OP 具​​有奇怪的数据结构,列表中的一些元素是对象,即节点,有些是列表,包含主列表中它们之前的节点的子节点.我认为他们只想对节点进行排序,并将子节点连接到这些节点。
      猜你喜欢
      • 1970-01-01
      • 2010-09-21
      • 2022-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多