Level up Sie Ihre .Sortieren Spiel

0
19

Die Sortierung ist eine super handliche JavaScript-Methode, die Anzeige der Werte eines Arrays in einer bestimmten Reihenfolge. Ob das Immobilien-Inserate nach Preis, burger Gelenke, durch die Entfernung, oder am besten in der Nähe glückliche Stunden, nach Bewertung, Sortieren von arrays von Daten ist eine Allgemeine Notwendigkeit.

Wenn Sie tun dies bereits mit JavaScript auf ein Projekt haben, sind Sie wahrscheinlich mit dem built-in-array .sort-Methode, die in der gleichen Familie von array-Methoden enthält .filter .anzeigen und .reduzieren.

Lassen Sie uns nehmen einen Blick auf, wie das zu tun!

Eine kurze Notiz über Nebenwirkungen

Bevor wir ins Detail gehen, wie zu verwenden .Art, es ist ein sehr wichtiges detail, das gelöst werden muss. Während viele der ES5 array-Methoden wie .filter .anzeigen, und .reduzieren liefern immer ein neues array und lassen das original unangetastet zu lassen .Sortieren Sortieren Sie das array in place. Wenn dies unerwünscht ist, ein ES6 Technik um dies zu vermeiden, ist die Verwendung der spread-operator zu erstellen, die kurz und prägnant ein neues array.

const foo = [‘c’,’b’,’a’];
const Leiste = [‘x’,’z’,’y’];
const fooSorted = foo.sort();
const barSorted = […bar].sort();

console.log ({“foo” fooSorted, bar, barSorted});

/*
{
“foo”: [ “a”, “b”, “c” ],
“fooSorted”: [ “a”, “b”, “c” ],
“bar”: [ “x”, “z”, “y” ],
“barSorted”: [ “x”, “y”, “z” ]
}
*/

foo und fooSorted beide verweisen auf das gleiche array, aber die bar und barSorted sind nun die einzelnen arrays.

Allgemeine übersicht

Der einzige parameter, der .sort-Methode ist eine Funktion. Die Skillung bezieht sich auf diese als die compareFn — ich wird bezeichnen Sie als die “Gegenüberstellung” für den rest der post. Dieser Vergleich-Funktion akzeptiert zwei Parameter, die ich zu beziehen, wie a und b. a und b sind die beiden Elemente, die wir vergleichen. Wenn Sie nicht eine Vergleich-Funktion, das array zwingen, jedes element in einen string und sortiert nach Unicode-Punkte.

Wenn Sie möchten, eine bestellt werden zuerst im array, die Vergleich-Funktion zurückgeben sollte eine negative ganze Zahl ist; für b eine positive ganze Zahl. Wenn Sie möchten, die beiden zu halten Ihre aktuelle Bestellung, Rückgabe 0.

Wenn Sie nicht verstehen, keine Sorge! Ich hoffe, es wird viel mehr klar, mit ein paar Beispiele.

Vergleichen von zahlen

Eine der einfachsten callbacks zu schreiben, ist eine Anzahl Vergleich.

const zahlen = [13,8,2,21,5,1,3,1];
byValue const = (a,b) => a – b;
const sortiert = [zahlen…].Sortieren(byValue);
console.log(sortiert); // [1,1,2,3,5,8,13,21]

Wenn a größer ist als b, a – b liefert eine positive Zahl, so b wird zuerst einmal geordnet werden.

Vergleichen von strings

Beim vergleichen von Zeichenfolgen, die < und > – Operatoren vergleichen Werte basierend auf den einzelnen string-Unicode-Wert. Dies bedeutet, dass alle Großbuchstaben wird “kleiner” als Kleinbuchstaben ein, das kann zu unerwartetem Verhalten führen.

JavaScript hat eine Methode, um mit dem vergleichen von strings: String.der Prototyp.localeCompare Methode. Diese Methode akzeptiert einen string-Vergleich, ein Gebietsschema, und ein Optionen-Objekt. Das options-Objekt akzeptiert ein paar Eigenschaften (von denen alle können Sie hier ansehen), aber ich finde, dass die meisten nützlich ist, ist “Sensibilität”. Dies wird beeinflussen, wie Arbeit Vergleiche zwischen Buchstaben-Variationen wie case und Akzent.

const strings = [‘Über’, ‘alpha’, ‘Eifer’, ‘über’, ‘uber’, ‘Uber’, ‘Alpha’, ‘Eifer’];

const sortBySensitivity = Empfindlichkeit => (a, b) => ein.localeCompare(
b,
undefined, // locale-string-undefiniert bedeutet Verwendung der Standard-browser
{ Empfindlichkeit }
);

const byAccent = sortBySensitivity(‘Akzent’);
const byBase = sortBySensitivity(‘base’);
const byCase = sortBySensitivity(‘Fall’);
const byVariant = sortBySensitivity(‘variant’); // default

const accentSorted = […strings].Sortieren(byAccent);
const baseSorted = […strings].Sortieren(byBase);
const caseSorted = […strings].Sortieren(byCase);
const variantSorted = […strings].Sortieren(byVariant);

console.log({accentSorted, baseSorted, caseSorted, variantSorted});

/*
{
“accentSorted”: [ “alpha”, “Alpha”, “uber”, “Uber”, “Über”, “über”, “Eifer”, “Eifer” ],
“baseSorted”: [ “alpha”, “Alpha”, “Über”, “über”, “uber”, “Uber”, “Eifer”, “Eifer” ],
“caseSorted”: [ “alpha”, “Alpha”, “über”, “über”, “Über”, “Uber”, “Eifer”, “Eifer” ],
“variantSorted”: [ “alpha”, “Alpha”, “uber”, “Uber”, “über”, “Über”, “Eifer”, “Eifer” ]
}
*/

Zu mir, baseSorted scheint die logischste für die meisten alphabetische Sortierung — ‘ü’, ‘u’, ‘Ü’ und ‘U’ sind äquivalent, also bleiben Sie in der Reihenfolge der ursprünglichen array.

Ausführen von Funktionen vor dem vergleichen der Werte

Sie möchten möglicherweise führen Sie eine Vergleich-Funktion auf einem Wert, abgeleitet ist jedes array-element. Zuerst schreiben wir eine Vergleichsfunktion, mit der Fabrik, dass die “Karte” über das element vor dem Aufruf der Vergleichs-Funktion.

const sortByMapped = (map,compareFn) => (a,b) => compareFn(map(a),map(b));

Ein Anwendungsfall HIERFÜR ist die Sortierung basiert auf dem Attribut eines Objekts.

const Einkäufe = [
{ name: ‘Popcorn’, Preis: 5.75 },
{ name: ‘Eintrittskarte’, Preis: 12 },
{ name: ‘Soda’, Preis: 3.75 },
{ name: ‘Candy’, Preis: 5 },
];

const sortByMapped = (map,compareFn) => (a,b) => compareFn(map(a),map(b));
byValue const = (a,b) => a – b;
const toPrice = e => e.Preis;
const byPrice = sortByMapped(toPrice,byValue);

console.log([…kauft].Sortieren(byPrice));

/*
[
{ name: “Soda”, Preis: 3.75 },
{ name: “Candy”, Preis: 5 },
{ name: “Popcorn”, Preis: 5.75 },
{ name: “Film-Ticket” Preis: 12 }
]
*/

Ein weiterer Fall könnte sein, zu vergleichen eine Reihe von Daten.

const Termine = [‘2018-12-10’, ‘1991-02-10’, ‘2015-10-07’, ‘1990-01-11’];
const sortByMapped = (map,compareFn) => (a,b) => compareFn(map(a),map(b));
const toDate = e => neu Termin(e).getTime();
byValue const = (a,b) => a – b;
const byDate = sortByMapped(toDate,byValue);

console.log([…Daten].Sortieren(byDate));
// [“1990-01-11”, “1991-02-10”, “2015-10-07”, “2018-12-10”]

Die Umkehrung einer Art

Es gibt einige Fälle, in denen Sie möglicherweise umkehren wollen, das Ergebnis eines Vergleich-Funktion. Dies ist subtil anders, als bei einem zu Sortieren und dann die Umkehrung des Ergebnisses in die Wege-verbindungen behandelt werden: wenn Sie reverse das Ergebnis, Krawatten auch in umgekehrter Reihenfolge.

Schreiben Sie eine höhere Ordnung, die Funktion akzeptiert eine Vergleich-Funktion und gibt eine neue ein, müssen Sie spiegeln die Zeichen der Vergleich ist-Wert zurückgeben.

const flipComparison = fn => (a,b) => -fn(a,b);
const byAlpha = (a,b) => ein.localeCompare(b, null, { sensitivity: ‘base’ });
const byReverseAlpha = flipComparison(byAlpha);

console.log([‘A’, ‘B’, ‘C’].Sortieren(byReverseAlpha)); // [‘C’,’B’,’A’]

Läuft tiebreaker Sortieren

Es gibt Zeiten, möchten Sie vielleicht, um eine “tie-breaker” – Art — das ist ein weiterer Vergleich-Funktion, die verwendet wird, im Fall von einem Band.

Durch die Verwendung von [].reduzieren Sie reduzieren können, ein array von Funktionen Vergleich zu einem einzigen.

const sortByMapped = anzeigen => compareFn => (a,b) => compareFn(map(a),map(b));
const flipComparison = fn => (a,b) => -fn(a,b);
byValue const = (a,b) => a – b;

const byPrice = sortByMapped(e => e.Preis)(byValue);
const byRating = sortByMapped(e => e.Bewertung)(flipComparison(byValue));

const sortByFlattened = fns => (a,b) =>
fns.reduce((acc, fn) => acc || fn(a,b), 0);

const byPriceRating = sortByFlattened([byPrice,byRating]);

const restaurants = [
{ name: “Foo’ s Burger Stand”, Preis: 1, rating: 3 },
{ name: “Die Tapas-Bar”, Preis: 3, rating: 4 },
{ name: “Baz Pizza”, Preis: 3, rating: 2 },
{ name: “Erstaunlich viel”, Preis: 1, rating: 5 },
{ name: “Überteuert”, Preis: 5, – Bewertung: 1 },
];

console.log(restaurants.Sortieren(byPriceRating));

/*
{name: “Erstaunlich viel”, Preis: 1, rating: 5}
{name: “Foo’ s Burger Stand”, Preis: 1, rating: 3}
{name: “Die Tapas-Bar”, Preis: 3, rating: 4}
{name: “Baz Pizza”, Preis: 3, rating: 2}
{name: “Überteuert”, Preis: 5, – Bewertung: 1}
*/

Schreiben Sie eine zufällige Sortierung

Möchten Sie vielleicht ein array Sortieren “zufällig.” Eine Technik, die ich gesehen habe ist die Verwendung der folgenden Funktion wie die Vergleich-Funktion.

const byRandom = () => Math.random() – .5;

Da Math.random() gibt eine “zufällige” Zahl zwischen 0 und 1, die byRandom Funktion zurückgeben sollte eine positive Zahl ist die Hälfte der Zeit und eine negative Zahl, die andere Hälfte. Dies scheint, wie es eine gute Lösung wäre, aber leider, da der Vergleich-Funktion ist nicht “konsistent” — also die kann es nicht geben den gleichen Wert zurück, wenn Sie aufgerufen mehrmals mit dem gleichen Werte — es kann dazu führen, dass einige unerwartete Ergebnisse.

Zum Beispiel, nehmen wir ein array von zahlen zwischen 0 und 4. Wenn diese byRandom Funktion war wirklich zufällig, es würde erwartet werden, dass der neue index der jede Zahl würde sich aus gleichmäßig über genügend Iterationen. Der ursprüngliche Wert 0 wäre ebenso wahrscheinlich werden im index-4 index 0 in das neue array. In der Praxis jedoch, diese Funktion wird bias jede Zahl in seine ursprüngliche position.

Siehe Stift
Array.sort() Random 👎 von Adam Giese (@AdamGiese)
auf CodePen.

Die “Diagonale” aus den top-Links werden rein statistisch haben Sie den größten Wert. In einer idealen und wirklich zufällige Art, jede Zelle in der Tabelle würde bewegen sich um 20%.

Die Lösung für dieses Problem ist, einen Weg zu finden, um sicherzustellen, dass die Vergleich-Funktion bleibt gleich. Ein Weg dies zu tun ist die Karte der zufällige Wert für jedes array-element vor dem Vergleich, ordnen Sie es sofort nach.

const sortByMapped = anzeigen => compareFn => (a,b) => compareFn(map(a),map(b));
const Werte = [0,1,2,3,4,5,6,7,8,9];
const withRandom = (e) => ({ random: Math.random(), original: e });
const toOriginal = ({original}) => original;
const toRandom = ({random}) => zufällige;
byValue const = (a,b) => a – b;
const byRandom = sortByMapped(toRandom)(byValue);

const shuffleArray = array => array
.Karte(withRandom)
.Sortieren(byRandom)
.Karte(toOriginal);

Dies stellt sicher, dass jedes element hat eine einzige zufällige Wert wird nur einmal berechnet je element und nicht als einmal pro Vergleich. Dadurch entfällt die Sortierung der bias in Richtung der ursprünglichen position.

Siehe Stift
Array.sort() Random 👍 von Adam Giese (@AdamGiese)
auf CodePen.