3

一つの質問に答えると、私は、より良い方法で行うことができたはずの迂回法であると私が信じる問題に行き着きましたが、私は無知でした

2つのリストがあります

percent = [0.23, 0.27, 0.4, 0.1]
optimal_partition = [3, 2, 2, 1]

optimal_partitionは、数値8を4つの部分に分割する整数分割の1つです。

optimal_partitionパーセンテージ分布を可能な限り一致させる方法で並べ替えたいと思います。つまり、個々のパーティションはパーセントの大きさに可能な限り一致する必要があります。

だから3 -> 0.42 -> 0.27そして0.23そして1 -> 0.1

したがって、最終結果は次のようになります。

[2, 2, 3, 1]

私がこれを解決することになった方法は

>>> percent = [0.23, 0.27, 0.4, 0.1]
>>> optimal_partition = [3, 2, 2, 1]
>>> optimal_partition_percent = zip(sorted(optimal_partition),
                    sorted(enumerate(percent),
                       key = itemgetter(1)))
>>> optimal_partition = [e for e, _ in sorted(optimal_partition_percent,
                          key = lambda e: e[1][0])]
>>> optimal_partition
[2, 2, 3, 1]

これを解決するためのより簡単な方法を提案できますか?

つまり、複数の並べ替えを実装したり、インデックスに基づいて保存したり、後で再配置したりする必要がないということです。

その他の例:

percent = [0.25, 0.25, 0.4, 0.1]
optimal_partition = [3, 2, 2, 1]
result = [2, 2, 3, 1]

percent = [0.2, 0.2, 0.4, 0.2]
optimal_partition = [3, 2, 2, 1]
result = [1, 2, 3, 2]
4

2 に答える 2

3
from numpy import take,argsort

take(opt,argsort(argsort(perc)[::-1]))

またはインポートなし:

zip(*sorted(zip(sorted(range(len(perc)), key=perc.__getitem__)[::-1],opt)))[1]

#Test

l=[([0.23, 0.27, 0.4, 0.1],[3, 2, 2, 1]),
   ([0.25, 0.25, 0.4, 0.1],[3, 2, 2, 1]),
   ([0.2,  0.2,  0.4, 0.2],[3, 2, 2, 1])]

def f1(perc,opt):
    return take(opt,argsort(argsort(perc)[::-1]))

def f2(perc,opt):
    return zip(*sorted(zip(sorted(range(len(perc)),
             key=perc.__getitem__)[::-1],opt)))[1]       

for i in l:
    perc, opt = i
    print f1(perc,opt), f2(perc,opt)

# output:
# [2 2 3 1] (2, 2, 3, 1)
# [2 2 3 1] (2, 2, 3, 1)
# [1 2 3 2] (1, 2, 3, 2)
于 2013-01-11T19:59:47.860 に答える
0

パーセンテージの合計が 1 になるという事実を使用します。

percent = [0.23, 0.27, 0.4, 0.1]
optimal_partition = [3, 2, 2, 1]
total = sum(optimal_partition)
output = [total*i for i in percent]

ここで、分数コンポーネントを何らかの形で再分配する方法を見つける必要があります。考えが口に出ていた:

from operator import itemgetter
intermediate = [(i[0], int(i[1]), i[1] - int(i[1])) for i in enumerate(output)]
# Sort the list by the fractional component
s = sorted(intermediate, key=itemgetter(2))
# Now, distribute the first item's fractional component to the rest, starting at the top:
for i, tup in enumerate(s):
    fraction = tup[2]
    # Go through the remaining items in reverse order
    for index in range(len(s)-1, i, -1):
        this_fraction = s[index][2]
        if fraction + this_fraction >= 1:
            # increment this item by 1, clear the fraction, carry the remainder
            new_fraction = fraction + this_fraction -1
            s[index][1] = s[index][1] + 1
            s[index][2] = 0
            fraction = new_fraction
        else:
            #just add the fraction to this element, clear the original element
            s[index][2] = s[index][2] + fraction

さて、それが「より簡単」だと言うかどうかはわかりません。私はそれをテストしていませんが、最後のセクションでロジックが間違っていると確信しています。実際、タプルへの代入を試みているので、少なくとも 1 つのエラーがあることがわかっています。しかし、それは別のアプローチです。

于 2013-01-11T19:54:42.000 に答える