如何根据这些子列表的某些规则和条件更改子列表列表中的项目?

时间:2014-04-28 20:13:52

标签: python list sublist

我有一个由三个项目组成的子列表列表。只有第一个和最后一个项目在子列表中很重要,因为我想根据列表中最后一个项目的频率更改所有子列表中的最后一个项目。

这是我的名单:

lst = [['A','abc','id1'],['A','def','id2'],['A','ghi','id1'],['A','ijk','id1'],['A','lmn','id2'],['B','abc','id3'],['B','def','id3'],['B','ghi','id3'],['B','ijk','id3'],['B','lmn','id'],['C','xyz','id6'],['C','lmn','id6'],['C','aaa','id5']]

例如,A出现最多的是id1而不是id2,因此我想用A替换所有与ID一起出现的id2。对于B,id3是最常见的,因此我想用id3替换任何其他任何实例,这意味着我想要替换“id' id'与' id3'仅适用于B.对于C,我想替换' id5'的实例。与' id6,'因为' id6'与列表一起出现最多。

Desired_List = lst = [['A','abc','id1'],['A','def','id1'],['A','ghi','id1'],['A','ijk','id1'],['A','lmn','id1'],['B','abc','id3'],['B','def','id3'],['B','ghi','id3'],['B','ijk','id3'],['B','lmn','id3'],['C','xyz','id6'],['C','lmn','id6'],['C','aaa','id6']]

我还应该提到,这将在一个非常大的列表中完成,因此需要速度和效率。

2 个答案:

答案 0 :(得分:1)

使用上面的ad-hoc要求进行直接数据处理,我可以提出以下算法。

第一次扫描:收集每个密钥的频率信息(即'A', 'B', 'C'):

def generate_frequency_table(lst):
    assoc = {}        # e.g. 'A': {'id1': 3, 'id2': 2}
    for key, unused, val in list:
        freqs = assoc.get(key, None)
        if freqs is None:
            freqs = {}
            assoc[key] = freqs
        valfreq = freqs.get(val, None)
        if valfreq is None:
            freqs[val] = 1
        else:
            freqs[val] = valfreq + 1
    return assoc

>>> generate_frequency_table(lst)
{'A': {'id2': 2, 'id1': 3}, 'C': {'id6': 2, 'id5': 1}, 'B': {'id3': 4, 'id': 1}}

然后,查看与每个键相关联的“值”(即{'A': 'id1'}):

def generate_max_assoc(assoc):
    max = {}    # e.g. {'A': 'id1'}
    for key, freqs in assoc.iteritems():
        curmax = ('', 0)
        for val, freq in freqs.iteritems():
            if freq > curmax[1]:
                curmax = (val, freq)
        max[key] = curmax[0]
    return max

>>> maxtable = generate_max_assoc(generate_frequency_table(lst))
>>> print maxtable
{'A': 'id1', 'C': 'id6', 'B': 'id3'}

最后,遍历原始列表并使用上表替换值:

>>> newlst = [[key, unused, maxtable[key]] for key, unused, val in lst]
>>> print newlst
[['A', 'abc', 'id1'], ['A', 'def', 'id1'], ['A', 'ghi', 'id1'], ['A', 'ijk', 'id1'], ['A', 'lmn', 'id1'], ['B', 'abc', 'id3'], ['B', 'def', 'id3'], ['B', 'ghi', 'id3'], ['B', 'ijk', 'id3'], ['B', 'lmn', 'id3'], ['C', 'xyz', 'id6'], ['C', 'lmn', 'id6'], ['C', 'aaa', 'id6']]

答案 1 :(得分:1)

这与Santa提供的解决方案几乎相同,但我将几个步骤合二为一,因为我们可以在收集频率时扫描最大值:

def fix_by_frequency(triple_list):
    freq = {}

    for key, _, value in triple_list:
        # Get existing data
        data = freq[key] = \
            freq.get(key, {'max_value': value, 'max_count': 1, 'counts': {}})

        # Increment the count
        count = data['counts'][value] = data['counts'].get(value, 0) + 1

        # Update the most frequently seen
        if count > data['max_count']:
            data['max_value'], data['max_count'] = value, count

    # Use the maximums to map the list
    return [[key, mid, freq[key]['max_value']] for key, mid, _ in triple_list]

这已经针对可读性进行了优化(我认为,很好!)而不是原始速度。例如,您可能不希望在不需要时写回dict,或者维护单独的max dict以防止最后列表理解中的两个键查找。