Es fällt mir schwer herauszufinden, wie man ein Array-Element verschiebt. Zum Beispiel, wenn Folgendes gegeben ist:
var arr = [ 'a', 'b', 'c', 'd', 'e'];
Wie kann ich eine Funktion schreiben, um sie 'd'
vorher zu verschieben 'b'
?
Oder 'a'
danach 'c'
?
Nach dem Verschieben sollten die Indizes der übrigen Elemente aktualisiert werden. Dies bedeutet, dass im ersten Beispiel nach der Bewegung arr [0] = 'a', arr [1] = 'd' arr [2] = 'b', arr [3] = 'c', arr [4] = 'e'
Das scheint ziemlich einfach zu sein, aber ich kann meinen Kopf nicht darum wickeln.
javascript
arrays
Mark Brown
quelle
quelle
const changeValuePosition = (arr, init, target) => {[arr[init],arr[target]] = [arr[target],arr[init]]; return arr}
init
und austarget
.Antworten:
Wenn Sie eine Version auf npm möchten, ist Array-Move dieser Antwort am nächsten, obwohl es nicht dieselbe Implementierung ist. Weitere Informationen finden Sie im Abschnitt zur Verwendung. Die vorherige Version dieser Antwort (die Array.prototype.move geändert hat) finden Sie auf npm unter array.prototype.move .
Ich hatte ziemlich gute Erfolge mit dieser Funktion:
Beachten Sie, dass der letzte
return
nur zu Testzwecken dient:splice
Führt Operationen am Array direkt aus, sodass eine Rückgabe nicht erforderlich ist. In der Erweiterung ist diesmove
eine In-Place-Operation. Wenn Sie dies vermeiden und eine Kopie zurückgeben möchten, verwenden Sieslice
.Durch den Code gehen:
new_index
es größer als die Länge des Arrays ist, möchten wir (nehme ich an) das Array richtig mit neuenundefined
s auffüllen. Dieses kleine Snippet behandelt dies, indem esundefined
auf das Array drückt, bis wir die richtige Länge haben.arr.splice(old_index, 1)[0]
spleißen wir das alte Element aus.splice
Gibt das Element zurück, das herausgespleißt wurde, aber es befindet sich in einem Array. In unserem obigen Beispiel war dies[1]
. Also nehmen wir den ersten Index dieses Arrays, um den Rohwert1
dort zu erhalten.splice
fügen wir dieses Element an der Stelle des neuen Index ein. Da wir das Array oben mit if aufgefüllt habennew_index > arr.length
, wird es wahrscheinlich an der richtigen Stelle angezeigt, es sei denn, sie haben etwas Seltsames getan, wie das Übergeben einer negativen Zahl.Eine schickere Version, um negative Indizes zu berücksichtigen:
Was Dinge wie
array_move([1, 2, 3], -1, -2)
richtig berücksichtigen sollte (verschieben Sie das letzte Element auf den vorletzten Platz). Ergebnis dafür sollte sein[1, 3, 2]
.So oder so, in Ihrer ursprünglichen Frage, würden Sie tun ,
array_move(arr, 0, 2)
füra
nachc
. Fürd
vorherb
würden Sie tunarray_move(arr, 3, 1)
.quelle
.hasOwnProperty
Prüfung, wenn sie mit Dingen wie for..in iterieren, insbesondere mit Bibliotheken wie Prototype und MooTools, die Prototypen modifizieren. Wie auch immer, ich hatte nicht das Gefühl, dass dies in einem relativ begrenzten Beispiel wie diesem ein besonders wichtiges Thema ist, und es gibt eine nette Spaltung in der Community darüber, ob eine Modifikation des Prototyps eine gute Idee ist oder nicht. Normalerweise sind Iterationsprobleme jedoch das geringste Problem.this[new_index] = undefined;
innerhalb desif
Blocks verwenden. Da Javascript-Arrays spärlich sind, wird die Array-Größe um den new_index erweitert, damit das.splice
funktioniert, ohne dass dazwischenliegende Elemente erstellt werden müssen.this[new_index] = undefined
wird tatsächlich einundefined
Array in den Array-Slot vor dem richtigen Index gesetzt. ([1,2,3].move(0,10)
Wird z. B.1
in Steckplatz 10 undundefined
in Steckplatz 9 haben.) Wenn die Spärlichkeit in Ordnung ist, könnten wirthis[new_index] = this.splice(old_index, 1)[0]
auf den anderen Spleißaufruf verzichten (machen Sie ihn stattdessen zu einem if / else).Hier ist ein Einzeiler, den ich auf JSPerf gefunden habe ...
Das ist großartig zu lesen, aber wenn Sie Leistung (in kleinen Datenmengen) wünschen, versuchen Sie ...
Ich kann keinen Kredit aufnehmen, alles sollte an Richard Scarrott gehen . In diesem Leistungstest übertrifft es die spleißbasierte Methode für kleinere Datensätze . Bei größeren Datenmengen ist es jedoch erheblich langsamer, wie Darwayne betont .
quelle
from >= to ? this.splice(to, 0, this.splice(from, 1)[0]) : this.splice(to - 1, 0, this.splice(from, 1)[0]);
Ich mag diesen Weg. Es ist prägnant und es funktioniert.
Hinweis: Denken Sie immer daran, Ihre Array-Grenzen zu überprüfen.
Führen Sie Snippet auf jsFiddle aus
quelle
Da die Funktion verkettbar ist, funktioniert dies auch:
Demo hier
quelle
Mein 2c. Einfach zu lesen, es funktioniert, es ist schnell, es werden keine neuen Arrays erstellt.
quelle
array
wie am Ende zurückkehren.Ich habe die Idee von @Reid, etwas an die Stelle des Elements zu schieben, das verschoben werden soll, um die Arraygröße konstant zu halten. Das vereinfacht die Berechnungen. Das Verschieben eines leeren Objekts hat außerdem den zusätzlichen Vorteil, dass es später eindeutig gesucht werden kann. Dies funktioniert, weil zwei Objekte nicht gleich sind, bis sie sich auf dasselbe Objekt beziehen.
Hier ist also die Funktion, die das Quellarray und die Quell- und Zielindizes berücksichtigt. Sie können es bei Bedarf zum Array.prototype hinzufügen.
quelle
sourceIndex = 0
,destIndex = 1
destIndex
soll der Index sein, bevor das Quellelement in das Array verschoben wird.Dies basiert auf der Lösung von @ Reid. Außer:
Array
Prototyp nicht.undefined
Elemente erstellt, sondern nur das Objekt an die Position ganz rechts verschoben.Funktion:
Unit Tests:
quelle
Hier ist meine Einzeiler-ES6-Lösung mit einem optionalen Parameter
on
.Anpassung der ersten von vorgeschlagenen Lösung
digiguru
Der Parameter
on
ist die Anzahl der Elemente, ab denenfrom
Sie sich bewegen möchten.quelle
Ein Ansatz wäre, mithilfe der Slice-Methode ein neues Array mit den Teilen in der gewünschten Reihenfolge zu erstellen.
Beispiel
quelle
arr2
aufgrund der Verkettungsoperationen eine Zeichenfolge sind, oder? :) Es endet damit"adc,de"
.Die
splice
Methode vonArray
könnte helfen: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/spliceDenken Sie daran, dass dies relativ teuer sein kann, da das Array aktiv neu indiziert werden muss.
quelle
Sie können einige grundlegende Berechnungen implementieren und eine universelle Funktion zum Verschieben von Array-Elementen von einer Position zur anderen erstellen.
Für JavaScript sieht es so aus:
Weitere Informationen finden Sie unter "Verschieben von Array-Elementen" unter "gloommatter".
http://www.gloommatter.com/DDesign/programming/moving-any-array-elements-universal-function.html
quelle
Ich habe hier eine unveränderliche
ECMAScript 6
Lösung implementiert , die auf der@Merc
Antwort von basiert :Die Variablennamen können gekürzt werden, nur lange, damit sich der Code selbst erklären kann.
quelle
array
sofort zurückkehrenfromIndex === toIndex
und nur dann erstellen,newArray
wenn dies nicht der Fall ist? Unveränderlichkeit bedeutet nicht, dass pro Funktionsaufruf eine neue Kopie erstellt werden muss, auch wenn keine Änderung vorliegt. Nur b / c nach dem Motiv für die längere Länge dieser Funktion zu fragen (im Vergleich zu Einzeilern auf Spleißbasis), ist Leistung undfromIndex
kanntoIndex
je nach Verwendung häufig gleich sein .Ich brauchte eine unveränderliche Verschiebungsmethode (eine, die das ursprüngliche Array nicht geändert hat), also habe ich die akzeptierte Antwort von @ Reid angepasst, um einfach Object.assign zu verwenden, um eine Kopie des Arrays zu erstellen, bevor der Spleiß ausgeführt wird.
Hier ist eine jsfiddle, die es in Aktion zeigt .
quelle
http://plnkr.co/edit/JaiAaO7FQcdPGPY6G337?p=preview
quelle
Am Ende habe ich zwei davon kombiniert, um beim Bewegen kleiner und großer Entfernungen etwas besser zu arbeiten. Ich erhalte ziemlich konsistente Ergebnisse, aber dies könnte wahrscheinlich von jemandem, der klüger als ich ist, ein wenig optimiert werden, um für verschiedene Größen usw. unterschiedlich zu arbeiten.
Die Verwendung einiger anderer Methoden beim Bewegen von Objekten über kleine Entfernungen war erheblich schneller (x10) als die Verwendung von Spleiß. Dies kann sich je nach Array-Länge ändern, gilt jedoch für große Arrays.
http://jsperf.com/arraymove-many-sizes
quelle
Es wird an vielen Stellen angegeben ( Hinzufügen von benutzerdefinierten Funktionen zu Array.prototype ), dass das Spielen mit dem Array-Prototyp eine schlechte Idee sein könnte. Trotzdem habe ich das Beste aus verschiedenen Posts kombiniert und dabei modernes Javascript verwendet:
Hoffnung kann für jeden nützlich sein
quelle
Diese Version ist nicht für alle Zwecke ideal, und nicht jeder mag Kommaausdrücke, aber hier ist ein Einzeiler, der ein reiner Ausdruck ist und eine neue Kopie erstellt:
Eine leicht leistungsverbesserte Version gibt das Eingabearray zurück, wenn keine Verschiebung erforderlich ist. Für die unveränderliche Verwendung ist es weiterhin in Ordnung, da sich das Array nicht ändert und es immer noch ein reiner Ausdruck ist:
Der Aufruf von beiden ist
Das heißt, es ist auf die Verbreitung angewiesen, um eine neue Kopie zu erstellen. Die Verwendung einer festen Arität 3
move
würde entweder die Eigenschaft eines einzelnen Ausdrucks oder die zerstörungsfreie Natur oder den Leistungsvorteil von gefährdensplice
. Auch hier handelt es sich eher um ein Beispiel, das einige Kriterien erfüllt, als um einen Vorschlag für die Verwendung in der Produktion.quelle
Array.move.js
Zusammenfassung
Verschiebt Elemente innerhalb eines Arrays und gibt ein Array zurück, das die verschobenen Elemente enthält.
Syntax
Parameter
index : Index, um den Elemente verschoben werden sollen. Wenn negativ, beginnt der Index am Ende.
howMany : Anzahl der Elemente, die aus dem Index verschoben werden sollen .
toIndex : Index des Arrays, in dem die verschobenen Elemente platziert werden sollen. Wenn negativ, beginnt toIndex am Ende.
Verwendungszweck
Polyfill
quelle
.move
aussieht, als ob es funktionieren sollte (ich habe es nicht getestet), sollten Sie beachten, dass es nicht Teil eines Standards ist. Es ist auch gut, die Leute zu warnen, dass Polyfill / Monkeypatched-Funktionen einen Code beschädigen können, der davon ausgeht, dass alles, was aufzählbar ist, ihnen gehört.Ich habe die nette Antwort von @Reid verwendet , aber Schwierigkeiten gehabt , ein Element vom Ende eines Arrays einen Schritt weiter zu verschieben - zum Anfang (wie in einer Schleife ). Zum Beispiel sollte ['a', 'b', 'c'] durch Aufrufen von .move (2,3) zu ['c', 'a', 'b'] werden.
Ich habe dies erreicht, indem ich den Fall für new_index> = this.length geändert habe.
quelle
Als Ergänzung zu Reids ausgezeichneter Antwort (und weil ich nichts kommentieren kann); Sie können Modulo verwenden, um sowohl negative als auch zu große Indizes "überrollen" zu lassen:
quelle
quelle
Ich dachte, das wäre ein Tauschproblem, aber das ist es nicht. Hier ist meine Einzeiler-Lösung:
Hier ist ein kleiner Test:
quelle
Ergebnis:
quelle
quelle
quelle
Unveränderliche Version ohne Array-Kopie:
quelle
Ich denke, der beste Weg ist, eine neue Eigenschaft für Arrays zu definieren
quelle
Eine weitere reine JS-Variante mit ES6-Array-Spread-Operator ohne Mutation
quelle
Diese Methode behält das ursprüngliche Array bei und prüft auf Begrenzungsfehler.
quelle