4

手头的问题:

我有以下元组列表(ID,Country),我最终将存储在 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 是否矫枉过正?

我从一个元组(luples)列表开始,将其转换为字典,执行干净的操作,然后将其转换回 luples?

我可以在 MySQL 表中插入原始的 luples,然后用很少的查询处理“未知”和“其他”,但我更喜欢 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 回答