2011-02-06 18 views
0

私はいくつかのデータを正規化する関数を書くことを考えていました。単純なアプローチは、私は内側のインデックス上でこのdoesntの仕事を正常化したいネストされたリストとdictsのためしかし変更されたネストされたdict/listを変更します。

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] 

です。私は、このようなノーマライズ機能を実装する方法

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がそのような構文を提供していることを知りました。私が省略記号のトリックを自分で実装する方法は誰でも知っていますか?

+0

作るために、任意の重要な理由のiterableの各要素は(ない場合は、以前のマージ機能を選択することで、それがより効率的に行うことができます)異なる可能性があると仮定すると新しいオブジェクトを作成するのではなく、インプレース操作ですか?それはわずかに遅くなるかもしれませんが、長期的には報われます。 – tokland

答えて

0

使用この:1(通常は重要でない)副作用があり

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

:内側のリストはタプルに変換されます。ただし、これは[list(el) for el in zip(normalize(zip(*l)[0]), zip(*l)[1])]で修正できます。

dictがある場合は、正規化が必要な値{'a': 1, 'b': 2}のように見えます。あなたはl.items()を使って、上記のトリックを使用することができます。

dict(zip(normalize(zip(*l.items())[0]), zip(*l.items())[1])) 

EDIT:

をあなたはこのような何か行うことができます:

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) 
+0

私は長時間で快適になるように正規化関数を拡張する方法を好むかもしれません:)そして、シーケンスが非常に大きくなる可能性があるので、あまり変形しません。どちらかというと、正規化(l、further_access = ?? [0]) – Gerenuk

4
で関数を呼び出します

私はthに何も変わるとは思わないe 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]] 
0

インプレースを変更する代わりに新しいオブジェクトを作成することをおすすめします。

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") 
関連する問題