在Python中使用Multiconditions对元组列表进行排序

时间:2012-11-11 23:33:08

标签: python sorting

我正在使用Python 2.6.2。我有一个元组pair列表,我喜欢使用两个嵌套条件进行排序。

  1. 元组首先按fwd_count的递减计数顺序排序,
  2. 如果fwd_count中多个元组的count值相同,则只有那些具有相同计数的元组需要根据rvs_count中的值按降序排序。
  3. 如果顺序无关紧要,可以忽略定位 a)元组在fwd_countrvs_count中具有相同的计数,或者 a)元组在fwd_count中具有相同的计数,在rvs_count
  4. 中不存在

    我设法编写了以下代码:

    pair=[((0, 12), (0, 36)), ((1, 12), (0, 36)), ((2, 12), (1, 36)), ((3, 12), (1, 36)), ((1, 36), (4, 12)), ((0, 36), (5, 12)), ((1, 36), (6, 12))]
    
    fwd_count = {}
    rvs_count = {}
    
    for link in sorted(pair):  
        fwd_count[link[0]] = 0
        rvs_count[link[1]] = 0
    
    for link in sorted(pair):  
        fwd_count[link[0]] += 1
        rvs_count[link[1]] += 1
    
    #fwd_count {(6, 12): 1, (5, 12): 1, (4, 12): 1, (1, 36): 2, (0, 36): 2}
    #rvs_count {(3, 12): 1, (1, 12): 1, (1, 36): 2, (0, 12): 1, (2, 12): 1, (0, 36): 1}
    
    fwd_count_sort=sorted(fwd_count.items(), key=lambda x: x[1], reverse=True)
    rvs_count_sort=sorted(rvs_count.items(), key=lambda x: x[1])
    
    #fwd_count_sort [((1, 36), 2), ((0, 36), 2), ((6, 12), 1), ((5, 12), 1), ((4, 12), 1)]
    #rvs_count_sort [((3, 12), 1), ((1, 12), 1), ((1, 36), 2), ((0, 12), 1), ((2, 12), 1), ((0, 36), 1)]
    

    我要找的结果是:

    #fwd_count_sort_final [((0, 36), 2), ((1, 36), 2), ((6, 12), 1), ((5, 12), 1), ((4, 12), 1)]
    

    (1, 36)(0, 36)的位置与fwd_count_sort中的位置交换位置。

    问题:

    1. 是否有更好的方法可以同时使用fwd_countrvs_count信息进行多条件排序? (只有元组很重要,无需记录排序值。)或
    2. 我是否需要针对每个条件单独进行排序(如上所述)并尝试找到将其整合以获得我想要的结果的意思?
    3. 我目前正在处理上面的第2项,但是试图了解是否有更简单的方法。

      这是我能在http://stygianvision.net/updates/python-sort-list-object-dictionary-multiple-key/找到我正在寻找的“与数字值双向排序”的最接近但不确定如果我用{tuple:{fwd_count:rvs_count创建一个新词典的话,我可以使用它关系。

      更新:2012年11月12日 - 已解决

      我已经设法通过使用列表来解决这个问题。以下是代码,希望它对那些正在排序多条件列表的人有用。

      #pair=[((0, 12), (0, 36)), ((1, 12), (1, 36)), ((2, 12), (0, 36)), ((3, 12), (1, 36)), ((1, 36), (4, 12)), ((0, 36), (5, 12)), ((1, 36), (6, 12))]
      
      rvs_count = {}
      fwd_count = {}
      
      for link in sorted(pair):
        rvs_count[link[0]] = 0
        fwd_count[link[1]] = 0
      
      for link in sorted(pair):
        rvs_count[link[0]] += 1
        fwd_count[link[1]] += 1
      
      keys = []
      for link in pair:
          if link[0] not in keys:
              keys.append(link[0])
          if link[1] not in keys:
              keys.append(link[1])
      
      aggregated = []
      for k in keys:
          a = -1
          d = -1
          if k in fwd_count.keys():
              a = fwd_count[k]
          if k in rvs_count.keys():
              d = rvs_count[k]
          aggregated.append(tuple((k, tuple((a,d)) )))
      
      def compare(x,y):
          a1 = x[1][0]
          d1 = x[1][1]
          a2 = y[1][0]
          d2 = y[1][1]
          if a1 > a2:
              return  - a1 + a2
          elif a1 == a2:
              if d1 > d2:
                  return d1 - d2
              elif d1 == d2:
                  return 0
              else:
                  return d1 - d2
          else:
              return - a1 + a2
      
      s = sorted(aggregated, cmp=compare)
      print(s)
      
      j = [v[0] for v in s]
      print(j)
      

      感谢Andre Fernandes,Brian和Duke对我的工作提出意见

2 个答案:

答案 0 :(得分:1)

如果您需要首先交换所有(对)元素(而不仅仅是(1, 36)(0, 36)),您可以执行此操作 fwd_count_sort=sorted(rvs_count.items(), key=lambda x: (x[0][1],-x[0][0]), reverse=True)

答案 1 :(得分:0)

我不完全确定排序条件的定义,但这是根据pairfwd_count中的值对rvs_count列表进行排序的方法。希望您可以使用它来获得您想要的结果。

def keyFromPair(pair):
    """Return a tuple (f, r) to be used for sorting the pairs by frequency."""
    global fwd_count
    global rvs_count

    first, second = pair
    countFirstInv = -fwd_count[first] # use the negative to reverse the sort order
    countSecond   = rvs_count[second]

    return (first, second)

pairs_sorted = sorted(pair, key = keyFromPair)

基本思想是使用Python的内置元组排序机制对多个键进行排序,并反转元组中的一个值,使其成为逆序排序。