2012-11-11 123 views
0

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

  1. 的元组的降序fwd_count计数顺序第一排序,
  2. 如果计数的值是用于fwd_count多于一个元组是相同的,只需要那些具有相等计数的元组以降序进行排序基于rvs_count中的值。
  3. 的顺序并不重要,定位可以忽略不计,如果 一)元组在fwd_count相同的计数,并在rvs_count,或 一)元组具有相同的计数fwd_countrvs_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_count,并在同一时间rvs_count信息分类? (只有元组很重要,不需要记录排序值),或
  2. 我需要为每个条件单独对它进行排序(正如我上面所做的那样),并尝试找到将其整合以获得结果的意思I通缉?

我目前正在研究上述项目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) 

感谢安德烈·费尔南德斯,布赖恩和杜克大学对我的工作给你的意见

+0

你能解释一下你为什么要((6,12),1)排序之前((5,12),1)在结果? – wim

+0

@wim我错过了提及那些在“fwd_count”和“rvs_count”(如果存在)中具有相同计数的人的顺序无关紧要。由于fwd_count是按降序排序的,因此每当count是相同的时候,python list会根据“link”id对它进行降序排序,因为((6,12),1)>((5,12),1) ((6,12),1)在((5,12),1)之前排序。但对我而言并不重要。希望我澄清得很好。感谢您的询问。 –

+1

我不明白这个模式?为什么一切都被切换? – enginefree

回答

1

如果您需要交换所有第一个(对)元素(而不仅仅是(1, 36)(0, 36)),你可以做 fwd_count_sort=sorted(rvs_count.items(), key=lambda x: (x[0][1],-x[0][0]), reverse=True)

0

我不是你的排序标准的定义完全相信,但是这是一个方法来排序pair列表根据fwd_countrvs_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的内置元组排序机制进行排序多个键,并且反转值中的一个元组,从而使其成为反向排序。

+0

仍然不能解决我的问题。 – Duke

相关问题