5

私がリストを持っているとしましょう:

L = [15,16,57,59,14]

リストには、あまり正確ではない測定値が含まれています。つまり、要素の実際の値は、記録された値の+-2です。したがって、14、15、および16は同じ値を持つことができます。私がやりたいのは、測定エラーを考慮して、そのリストを一意化することです。そのため、出力は次のようになります。

l_out = [15,57]

また

l_out = [(14,15,16),(57,59)]

forループでどちらの結果も問題なく生成できます。しかし、もっとエレガントな解決策があるかどうか興味があります。アイデアは大いに応用されました。

4

4 に答える 4

5

lazyrがコメントで指摘したように、同様の問題がここに投稿されています。クラスタモジュールを使用すると、私の問題の解決策は次のようになります。

>>> from cluster import *
>>> L = [15,16,57,59,14]
>>> cl = HierarchicalClustering(L, lambda x,y: abs(x-y))
>>> cl.getlevel(2)
[[14, 15, 16], [57, 59]]

または(各グループの平均値を含む一意のリストを取得するには):

>>> [mean(cluster) for cluster in cl.getlevel(2)]
[15, 58]
于 2012-06-22T11:38:17.857 に答える
2

標準のlibpythonが必要な場合は、itertool'sgroupbyが友達です。

from itertools import groupby

L = [15,16,57,59,14]

# Stash state outside key function. (a little hacky).
# Better way would be to create stateful class with a __call__ key fn.
state = {'group': 0, 'prev': None}
thresh = 2

def _group(cur):
    """Group if within threshold."""
    if state["prev"] is not None and abs(state["prev"] - cur) > thresh:
        state["group"] += 1 # Advance group
    state["prev"] = cur
    return state["group"]

# Group, then drop the group key and inflate the final tuples.
l_out = [tuple(g) for _, g in groupby(sorted(L), key=_group)]

print l_out
# -> [(14, 15, 16), (57, 59)]
于 2012-06-22T12:01:30.357 に答える
2

純粋なPythonアプローチでこれを行う方法は次のとおりです。

s = sorted(L)
b = [i + 1 for i, (x, y) in enumerate(zip(s, s[1:])) if y > x + 2]
result = [s[i:j] for i, j in zip([None] + b, b + [None])]

bこれは、クラスターが終了するインデックスである「ブレーク」のリストです。

于 2012-06-22T12:56:34.770 に答える
-1

forループが最も簡単な方法ですが、本当に1行のコードが必要な場合:
l_out = list(set(tuple([tuple(filter(lambda i: abs(item - i) < 3, L)) for item in L])))
非常に不明確ですが、forバージョンをお勧めします:)

于 2012-06-22T11:21:05.150 に答える