4

手元の問題:

次のタプルのリスト(ID、国)があり、最終的にMySQLテーブルに格納します。

mylist = [(10, 'Other'), (10, 'India'), (10, 'Unknown'), (11, 'Other'), (11, 'Unknown'), (12, 'USA'), (12, 'UK'), (12, 'Other')]

次の条件を使用して、「その他」と「不明」を処理したい:

Value       Replaced by => This value
----------------------------------------
Other & Unknown         => Other
A country & Other       => Country
A country & Unknown     => Country

Python:

def refinelist(mylist):

    '''Updating the list to remove unwanted values'''
    '''
    Other & Unknown => Other
    A country & Other => Country
    A country & Unknown => Country
    '''

    if 'Other' in mylist and 'Unknown' in mylist:
        print 'remove unknown'
        mylist.remove('Unknown')
    if 'Other' in mylist and len(mylist) >= 2:
        print 'remove other'
        mylist.remove('Other')
    if 'Unknown' in mylist and len(mylist) >= 2:
        print 'remove unknown'
        mylist.remove('Unknown')

    return mylist

def main():

    mylist = [(10, 'Other'), (10, 'India'), (10, 'Unknown'), (11, 'Other'), (11, 'Unknown'), (12, 'USA'), (12, 'UK'), (12, 'Other')]

    d = {}

    for x,y in mylist:
        d.setdefault(x, []).append(y)

    # Clean the list values    
    for each in d:
        d[each] = refinelist(d[each])

    ## Convert dict to list of tuples for database entry

    outlist = []

    #result = [(key, value) for key,value in d.keys(), value in d.values()]  ## Couldn't get this to work. Can the below loop be written as list comprehension with minimal footprint?

    for key, value in d.items():
        if len(value) == 1:
            print key, value[0]
            outlist.append((key, value[0]))
        elif len(value) > 1:
            for eachval in value:
                print key, eachval
                outlist.append((key, eachval))

    print outlist

if __name__ == "__main__":
    main()    

出力:

remove unknown
remove other
remove unknown
remove other
10 India
11 Other
12 USA
12 UK
[(10, 'India'), (11, 'Other'), (12, 'USA'), (12, 'UK')]

質問 :

これはもっと効率的にできると思います。ディクトオーバーキルを使用していますか?

タプル(ルプル)のリストから始めて、それをdictに変換し、クリーンな操作を実行してから、ルプルに変換し直しますか?

MySQLテーブルに元のループを挿入してから、いくつかのクエリで「不明」と「その他」を処理することもできますが、タスクにはPythonを使用します。

pythonicソリューションまたはコードに関する批評家は大歓迎です。

4

3 に答える 3

6

ジェネレータとリスト内包表記を多用すると、次のように記述できます。

other = ['Other', 'Unknown']                        # Strings denoting non-contries
ids = set(i for i,j in mylist)                      # All ids in the list
known = set(i for i,j in mylist if j not in other)  # Ids of real countries
outlist = [k for k in mylist if k[1] not in other]  # Keep all real countries
outlist.extend((i, other[0]) for i in ids - known)  # Append "Other" for all IDs with no real country

結果は次のようになります

[(10, 'India'), (12, 'USA'), (12, 'UK'), (11, 'Other')]

順序が重要な場合、これはより多くの作業を意味します。

于 2012-08-08T14:47:52.850 に答える
2

一つには、あなたのコードは、削除呼び出しごとに大量の高価なリスト操作をもたらします。順序が重要な場合は、最初に並べ替えてからリストをもう一度確認するだけで、次のことができます。(私はこれをジェネレーターとして作成したので、(1)必要がない場合(たとえば、これをデータベースに追加する場合)にリストを作成する必要がなく、(2)回避するためにすべての追加操作。

def filter_list(lst):
    lst = sorted(lst)
    curr_id = lst[0][0]
    found_country = False
    for id, elem in lst:
        if id != curr_id:
            if not found_country:
                yield (curr_id, "Other")
            curr_id = id
            found_country=False
        if elem not in ("Other", "Unknown"):
            yield (curr_id, elem)
            found_country = True

リストを取り戻したいだけの場合は、list(filter_list(input_list))を使用します。(それが最もエレガントではないことを自由に認めてください)

于 2012-08-08T14:55:45.430 に答える
0

より短いがおそらくより遅い解決策:

    na_list = ['Other', 'Unknown']
    data = dict()
    result = list()

    for i in mylist:
        k = str(i[0])
        data.setdefault(k, [])
        data[k].append(i[1])

    for k,v in data.iteritems():
       if not len(set(v) - set(na_list)):
           result.append((int(k), na_list[0]))
    else:
       for c in set(v) - set(na_list):
           result.append((int(k), c))
于 2012-08-08T16:12:48.627 に答える