2013-12-08 59 views
1

在python中,我有一個名爲category的字符串字段的類列表。 讓我們看看下面的例子:按照python中的第一個分組進行排序?

mylist[0].category # = "furniture" 
mylist[1].category # = "car" 
mylist[2].category # = "fruit" 
mylist[3].category # = "car" 
mylist[4].category # = "furniture" 

我的問題是:如何重新安排使用一個新的類別中第一次出現的分組名單?

使用前面的例子,其結果必然是:

mylist[0].category # = "furniture" 
mylist[1].category # = "furniture" 
mylist[2].category # = "car" 
mylist[3].category # = "car" 
mylist[4].category # = "fruit" 
+0

@codehorse用鍵來排序();你可能想把它作爲答案。 :) – SuperSaiyan

回答

2

首先,以相同的順序獲得的類別列表爲my_list。然後,根據每個項目類別在類別列表中首次出現的位置對my_list進行排序。

categories = [item.category for item in my_list] 
my_list.sort(key = lambda item: categories.index(item.category)) 
+0

重複'.index'搜索將會非常緩慢,因爲有足夠多的類別。至少使'類別'是一個'dict',以便查找是恆定的時間而不是O(n) – roippi

+0

簡單而有效,但肯定不是最優化的方式來實現這一點(但可擴展性不是我的問題)。 – Vincent

+0

很高興幫助您使用@ HughBothwell的解決方案,如果您想稍微優化一些東西。 – Stuart

1
# create a first-appearance index 
order = {} 
for ndx,item in enumerate(mylist): 
    if item.category not in order: 
     order[item.category] = ndx 

# sort by that index 
mylist.sort(key=lambda i: order[i]) 
+0

mylist沒有分類屬性(但每個元素都有) – Vincent

+0

@Vincent:是一個錯字,現在已修復。 –

0

你可以通過遍歷列表兩次(不排序)實現這一點:

from collections import defaultdict 

# put all the items of the same category together 
l = defaultdict(list) 
for x in mylist: 
    l[ x.category ].append(x) 

# expand in the order categories appear in the list 
xs = [ ] 
for x in mylist: 
    xs.extend(l[ x.category ]) 
    l.pop(x.category) 
0

也許這樣的事情?

#!/usr/local/cpython-3.3/bin/python 

import pprint 


CATEGORY_FIRST_SEEN = {} 


def extract_order(list_of_class): 
    for index, element in enumerate(list_of_class): 
     if element.category not in CATEGORY_FIRST_SEEN: 
      CATEGORY_FIRST_SEEN[element.category] = index 

    #pprint.pprint(CATEGORY_FIRST_SEEN) 


class Class_with_category: 
    def __init__(self, category): 
     self.category = category 

    def __cmp__(self, other): 
     if CATEGORY_FIRST_SEEN[self.category] < CATEGORY_FIRST_SEEN[other.category]: 
      return -1 
     elif CATEGORY_FIRST_SEEN[self.category] > CATEGORY_FIRST_SEEN[other.category]: 
      return 1 
     else: 
      return 0 

    def __lt__(self, other): 
     return self.__cmp__(other) < 0 

    def __str__(self): 
     return self.category 

    __repr__ = __str__ 


def main(): 
    mylist = [ "furniture", "car", "fruit", "car", "furniture", ] 
    list_of_class = [ Class_with_category(element) for element in mylist ] 
    extract_order(list_of_class) 
    list_of_class.sort() 
    pprint.pprint(list_of_class) 


main() 

我測試過它在cpython 3.3上工作,但我相信它應該可以在2.x或3.x上工作。

相關問題