9

指定された 16 進数値に応じて、最も一致する色の名前を取得しようとします。たとえば、hex-color がある場合#f00、 colorname を取得する必要がありredます。

'#ff0000' => 'red'
'#000000' => 'black'
'#ffff00' => 'yellow'

現在、レーベンシュタイン距離アルゴリズムを使用して最も近い色の名前を取得していますが、これまでのところうまく機能しますが、期待どおりにならないこともあります。

例えば:

'#0769ad' => 'chocolate'
'#00aaee' => 'mediumspringgreen'

それで、結果を近づける方法はありますか?

これが私が最も近い色を得るために作ったものです:

Array.closest = (function () {

    // http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript
    function levDist(s, t) {
        if (!s.length) return t.length;
        if (!t.length) return s.length;

        return Math.min(
            levDist(s.substring(1), t) + 1,
            levDist(t.substring(1), s) + 1,
            levDist(s.substring(1), t.substring(1)) + (s[0] !== t[0] ? 1 : 0)
        );
    }

    return function (arr, str) {
        // http://stackoverflow.com/q/11919065/1250044#comment16113902_11919065
        return arr.sort(function (a, b) {
            return levDist(a, str) - levDist(b, str);
        });
    };

}());

http://jsfiddle.net/ARTsinn/JUZVd/2/

もう一つは、パフォーマンスです!これを非常に遅くする非常に大きな問題がどこかにあるようです (それはアルゴリズムですか?)。

4

1 に答える 1

11

レーベンシュタイン距離は、文字ごとに等しいかどうかを比較するため、ここではあまり適切ではありません。各色を個別に確認する必要があり、よりも79はるかに近づけたいと思うでしょう。8000

以下は、コードへの最小限の変更のみで、あなたが望むものに非常に近いようです:

Array.closest = (function () {
    function dist(s, t) {
        if (!s.length || !t.length) return 0;
        return dist(s.slice(2), t.slice(2)) +
            Math.abs(parseInt(s.slice(0, 2), 16) - parseInt(t.slice(0, 2), 16));
    }

    return function (arr, str) {
        return arr.sort(function (a, b) {
            return dist(a, str) - dist(b, str);
        });
    };
}());

これは、sとの両方tが 6 文字のカラー 16 進コードである場合にのみ妥当な結果をもたらすことに注意してください。

最も近い色を取得するために配列全体を並べ替える必要がないため、コードは非効率的です。代わりに、配列をループして最短距離を追跡する必要があります。

例えば:

Array.closest = (function () {
    function dist(s, t) {
        if (!s.length || !t.length) return 0;
        return dist(s.slice(2), t.slice(2)) +
            Math.abs(parseInt(s.slice(0, 2), 16) - parseInt(t.slice(0, 2), 16));
    }

    return function (arr, str) {
        var min = 0xffffff;
        var best, current, i;
        for (i = 0; i < arr.length; i++) {
            current = dist(arr[i], str)
            if (current < min) {
                min = current
                best = arr[i];
            }
        }
        return best;
    };
}());

この変更の後Array.closest()、配列ではなく単一の値が返されるため[0]、コードのさらに下を削除する必要があることに注意してください。

于 2013-06-18T18:19:10.340 に答える