2013-06-18 4 views
6

Ich versuche, den passendsten Farbnamen abhängig von einem gegebenen Hex-Wert zu erhalten. Zum Beispiel, wenn wir die Hex-Farbe #f00 haben, müssen wir den Farbnamen red bekommen.Erhalte den nächsten Farbnamen in Abhängigkeit von einer Hex-Farbe

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

Ich verwende derzeit den levenshtein-Distanz-Algorithmus die nächsten Farbnamen zu bekommen, funktioniert gut, so weit, aber manchmal nicht wie erwartet.

Zum Beispiel:

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

So irgendwelche Ideen, wie das Ergebnis näher kommen?

Hier ist, was ich machte die nächste Farbe zu erhalten:

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/

Eine andere Sache ist die Leistung! Es scheint, dass es irgendwo ein wirklich großes Problem gibt, das das wirklich langsam macht (ist es der Algorithmus?).

+1

Für ähnlichere Farben wäre es besser, stattdessen [HSL] (https://en.wikipedia.org/wiki/HSL_and_HSV) Farben zu verwenden. – Sirko

+1

Sie könnten den Sortierschritt um ein Vielfaches beschleunigen, wenn Sie die Abstände vor dem Sortieren vorberechnen würden. – Pointy

+0

Auch ich bin mir nicht sicher, warum Sie nicht eine einfache kartesische Entfernungsberechnung verwenden würden. (Eigentlich würde ich in einen Winkelkoordinatenraum umrechnen und die Entfernung in HSL oder HSV terns machen.) – Pointy

Antwort

6

Levenshtein Entfernung ist hier nicht wirklich angemessen, weil es Zeichen für Zeichen für Gleichheit vergleichen wird. Sie müssen jede Farbe einzeln überprüfen und möchten, dass 79 viel näher an 80 als 00 ist.

Die folgende scheint ein gutes Stück näher zu sein, was Sie wollen, mit nur minimalen Änderungen an Ihrem Code:

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); 
     }); 
    }; 
}()); 

Beachten Sie, dass dies nur vernünftige Ergebnisse geben wird, wenn beide s und t 6-Zeichenfarbe sind Hex-Codes.

Ihr Code ist ineffizient, da Sie nicht das gesamte Array sortieren müssen, um die nächste Farbe zu erhalten. Sie sollten stattdessen nur das Array durchlaufen und die kürzeste Entfernung verfolgen.

Zum Beispiel:

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; 
    }; 
}()); 

Beachten Sie, dass Array.closest() nach dieser Änderung einen einzelnen Wert zurückgeben wird, anstatt ein Array, so dass Sie die [0] weiter unten im Code entfernen müssen.

+0

Wow, großartig! Danke bis jetzt: - * * vernünftige Ergebnisse, wenn sowohl s als auch t 6-stellige Farb-Hex-Codes sind * Kein Problem Ich wandle 3-stellige Hex-Farben in 6 ein :) – yckart

+0

BTW: Pointe [erwähnt] (http: // stackoverflow .com/questions/17175664/get-the-engest-color-name-abhängig-auf-einem-hex-color # comment24869664_17175664), die die Entfernung vor der Sortierung vorberechnen macht es noch schneller ?! – yckart

+1

Sie sollten überhaupt nicht sortieren, siehe meine Bearbeitung. –

Verwandte Themen