修改传递的,嵌套的dict / list

时间:2011-02-06 20:24:03

标签: python

我正在考虑编写一个函数来规范化一些数据。一个简单的方法是

def normalize(l, aggregate=sum, norm_by=operator.truediv):
    aggregated=aggregate(l)
    for i in range(len(l)):
        l[i]=norm_by(l[i], aggregated)

l=[1,2,3,4]
normalize(l)
l -> [0.1, 0.2, 0.3, 0.4]

但是对于嵌套列表和dicts,我想在内部索引上进行规范化,这不起作用。我的意思是我想得到

l=[[1,100],[2,100],[3,100],[4,100]]
normalize(l, ?? )
l -> [[0.1,100],[0.2,100],[0.3,100],[0.4,100]]

我是如何实现这种规范化函数的?

编写

可能会很酷
normalize(l[...][0])

是否有可能使这项工作?还是其他任何想法?

此外,不仅列表而且dict也可以嵌套。嗯...

编辑: 我刚刚发现numpy提供了这样的语法(但是对于列表)。任何人都知道我将如何实现省略号技巧?

3 个答案:

答案 0 :(得分:4)

我认为不需要对normalize()函数进行任何更改。要处理嵌套列表,您只需提供正确的aggregate()norm_by()函数来处理案例。

l = [[1, 100], [2, 100], [3, 100], [4, 100]]
def aggregator(l):
    return sum(item[0] for item in l)

def normalizer(item , aggregated):
    # mutating the inner list
    item[0] = operator.truediv(item[0], aggregated)
    return item

normalize(l, aggregate = aggregator, norm_by = normalizer)
# l -> [[0.1, 100], [0.2, 100], [0.3, 100], [0.4, 100]]

答案 1 :(得分:0)

使用此:

zip(normalize(zip(*l)[0]), zip(*l)[1])

有一个(通常不重要)副作用:内部列表转换为元组。但是,可以使用[list(el) for el in zip(normalize(zip(*l)[0]), zip(*l)[1])]更正此问题。

如果你有一个字典,我想它看起来像{'a': 1, 'b': 2},这些值需要规范化。您可以使用l.items()

来使用上述技巧
dict(zip(normalize(zip(*l.items())[0]), zip(*l.items())[1]))

修改

你可以这样做:

def normalize(l, aggregate=sum, norm_by=operator.truediv, key=None):
    aggregated=aggregate(l)
    for i in range(len(l)):
        if key is not None:
            l[i][key] = norm_by(l[i][key], aggregated)
        else:
            l[i]=norm_by(l[i], aggregated)

调用该函数
normalize(l, key=0)

答案 2 :(得分:0)

我建议创建新对象而不是就地修改。假设iterable中的每个元素可能不同(如果没有,您可以通过之前选择合并函数使其更有效):

def normalize(input, index=None, aggregate=sum, norm_by=operator.truediv):
    aggregated = aggregate(input)
    for item in input:
        if isinstance(item, list):
            yield item[:index] + [norm_by(item[index], aggregated)] + item[index+1:]
        elsif isinstance(item, dict):
            yield dict(d, **{index: norm_by(item[index], aggregated)})
        else:
            yield norm_by(item, aggregated)

待用:

normalize([1, 2, 3])
normalize([(1, 2), (3, 4)], 0)
normalize([{"a": 1, "b": 2}, {"a": 3, "b": 4}], "a")