JavaScript move an item of an array to the front
JavascriptArraysJavascript Problem Overview
I want to check if an array contains "role"
. If it does, I want to move the "role"
to the front of the array.
var data= ["email","role","type","name"];
if ("role" in data) data.remove(data.indexOf("role")); data.unshift("role")
data;
Here, I got the result:
["role", "email", "role", "type", "name"]
How can I fix this?
Javascript Solutions
Solution 1 - Javascript
You can sort the array and specify that the value "role"
comes before all other values, and that all other values are equal:
var first = "role";
data.sort(function(x,y){ return x == first ? -1 : y == first ? 1 : 0; });
Solution 2 - Javascript
The cleanest solution in ES6 in my opinion:
let data = ["email","role","type","name"];
data = data.filter(item => item !== "role");
data.unshift("role");
Solution 3 - Javascript
My first thought would be:
var data= ["email","role","type","name"];
// if it's not there, or is already the first element (of index 0)
// then there's no point going further:
if (data.indexOf('role') > 0) {
// find the current index of 'role':
var index = data.indexOf('role');
// using splice to remove elements from the array, starting at
// the identified index, and affecting 1 element(s):
data.splice(index,1);
// putting the 'role' string back in the array:
data.unshift('role');
}
console.log(data);
To revise, and tidy up a little:
if (data.indexOf('role') > 0) {
data.splice(data.indexOf('role'), 1);
data.unshift('role');
}
References:
Solution 4 - Javascript
let data = [0, 1, 2, 3, 4, 5];
let index = 3;
data.unshift(data.splice(index, 1)[0]);
// data = [3, 0, 1, 2, 4, 5]
Solution 5 - Javascript
Here is an immutable solution if needed :
const newData = [
data.find(item => item === 'role'),
...data.filter(item => item !== 'role'),
],
Solution 6 - Javascript
If you don't want to alter the existing array, you can use ES6 destructuring with the filter method to create a new copy while maintaining the order of the other items.
const data = ["email", "role", "type", "name"];
const newData = ['role', ...data.filter(item => item !== 'role')];
Solution 7 - Javascript
To check whether an item exists in an array you should to use .includes()
instead of in
(as already noted here, in
is for properties in objects).
This function does what you are looking for: (removes the item from the position it is in and reads in front)
data = ["email","role","type","name"];
moveToFirst("role", data);
function moveToFirst( stringToMove, arrayIn ){
if ( arrayIn.includes(stringToMove) ){
let currentIndex = arrayIn.indexOf(stringToMove);
arrayIn.splice(currentIndex, 1);
arrayIn.unshift(stringToMove);
}
}
console.log(data);
Solution 8 - Javascript
If you have an array of objects you could shift the start-index with splice and push. Splice replaces the original array with the part of the array starting from the desired index and returns the part it removes (the stuff before the index) which you push.
let friends = [{
id: 1,
name: "Sam",
},
{
id: 2,
name: "Steven",
},
{
id: 3,
name: "Tom",
},
{
id: 4,
name: "Nora",
},
{
id: 5,
name: "Jessy",
}
];
const tomsIndex = friends.findIndex(friend => friend.name == 'Tom');
friends.push(...friends.splice(0, tomsIndex));
console.log(friends);
Solution 9 - Javascript
I would go with this ES6 solution. It doesn't mutate the original array(considering it's not nested), doesn't traverse through the array(filter) and you're not just limited to 0th index for shifting the array item.
const moveArrayItem = (array, fromIndex, toIndex) => {
const arr = [...array];
arr.splice(toIndex, 0, ...arr.splice(fromIndex, 1));
return arr;
}
const arr = ["a", "b", "c", "d", "e", "f", "g"];
console.log(moveArrayItem(arr, 4, 0))
// [ 'e', 'a', 'b', 'c', 'd', 'f', 'g' ]
Solution 10 - Javascript
Similar to @Tandroid's answer but a more general solution:
const putItemsFirst = ({ findFunction, array }) => [
...array.filter(findFunction),
...array.filter(item => !findFunction(item)),
];
Can be used like this
putItemsFirst({
array: ["email","role","type","name"],
findFunction: item => item === 'role',
})
Something similar to this is what I ended up using,
Solution 11 - Javascript
You could take the delta of the check with the wanted value at top.
var data = ["email", "role", "type", "name"];
data.sort((a, b) => (b === 'role') - (a === 'role'));
console.log(data);
Solution 12 - Javascript
A reusable ES6/Typescript solution:
const moveToStart = <T>(array: T[], predicate: (item: T) => boolean): T[] => {
return array.sort((a, b) => {
if (predicate(a)) return -1;
if (predicate(b)) return 1;
return 0;
});
};
const data = ["email", "role", "type", "name"];
const result = moveToStart(data, (item) => item === "role"))
Solution 13 - Javascript
- the
in
operator is about properties, not about items in arrays. See https://stackoverflow.com/q/237104/1048572 for what to use else. - You're missing braces around the two (!) statements in your if-block
- I'm not sure whether that
.remove()
function you're using does take an index of an item.
Solution 14 - Javascript
var data= ["email","role","type","name"];
data.splice(data.indexOf("role"), 1);
data.unshift('role');
Solution 15 - Javascript
Using lodash _.sortBy. If the item is role
, it will be sorted first, otherwise second. This works fine too if there is no role
var data = ["email", "role", "type", "name"];
var sorted = _.sortBy(data, function(item) {
return item === 'role' ? 0 : 1;
});
console.log(sorted);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
Solution 16 - Javascript
Just wanted to drop this on here since according to other comments Guffa's answer seems to be gaining traction, the final tertiary - which was one of the negative comments on that answer is unnecessary. Also using arrow functions makes it seem much cleaner.
Also, it is easily expandable to handling Arrays of objects.
const first = "role";
data.sort((x, y) => first === x ? -1 : first === y)
I believe this should also handle the worry of the rest of the array being affected. When the sort function returns a number less than 0 (first === x), the element will move toward the start of the Array, when it returns 0 (first !== y), there will be no movement, and when a number greater than 0 (first === y), x will move toward the end of the Array, all in relation to x and y. Therefore, when neither x or y are equivalent to the desired first element (or it's identifier in the case of sorting objects), there will be no movement of the two in relation to each other.
For an object:
const unsorted = [{'id': 'test'}, {'id': 'something'}, {'id': 'else'}];
const first = 'something';
const sorted = unsorted.sort((x,y) => x['id'] === first ? -1 : y['id'] === first);
Solution 17 - Javascript
Generalized one-liners:
const data = ["a", "b", "c", "d", "e", "f"];
const [from, take] = [3, 2];
data.unshift(...data.splice(from, take));
// alternatively
data = [...data.splice(from, take), ...data];
// ["d", "e", "a", "b", "c", "f"]
Solution 18 - Javascript
const moveToFront = (arr, queryStr) =>
arr.reduce((acc, curr) => {
if (queryStr === curr) {
return [curr, ...acc];
}
return [...acc, curr];
}, []);
const data = ['email', 'role', 'type', 'name'];
console.log(moveToFront(data, 'role'))
Solution 19 - Javascript
const moveTargetToBeginningOfArray = (arr, target) => {
// loop through array
for (let i = 0; i < arr.length; i++){
// if current indexed element is the target
if(arr[i] === target){
// remove that target element
arr.splice(i, 1)
// then add a target element to the beginning of the array
arr.unshift(target)
}
}
return arr;
};
// quick sanity check, before and after both are correct
const arrayOfStrings = ["email", "role", "type", "name", "role", "role"];
console.log('before:', arrayOfStrings)
console.log('after:', moveTargetToBeginningOfArray(arrayOfStrings, "role"))
// this would also work for numbers
var arrayOfNumbers = [2,4,0,3,0,1,0]
console.log('before:', arrayOfNumbers)
console.log('after:', moveTargetToBeginningOfArray(arrayOfNumbers, 0))
Solution 20 - Javascript
function unshiftFrom(arr, index) {
if (index > -1 && index < arr.length) { // validate index
var [itemToMove] = arr.splice(index, 1)
arr.unshift(itemToMove)
}
return arr // optional
}
Solution 21 - Javascript
var i = -1;
while (i < data.length) {
if (data[i] === "role") {
data.splice(i, 1);
break;
}
i++;
}
data.unshift("role");
indexOf
only has limited browser support, not being recognized by IE7-8. So I wouldn't use it if I were you, even at the expense of a few lines' worth of code conciseness. You also want to put a semicolon at the end of the "unshift" statement. splice()'s first argument specifies the index to start removing elements, and the second argument specifies the number of arguments to remove.
Solution 22 - Javascript
data.unshift(data.splice(data.indexOf('role'), 1)[0])
data.indexOf('role')
will find the index of 'role' in the array and then the original array is spliced to remove the 'role' element, which is added to the beginning of the array using unshift
Solution 23 - Javascript
var data= ["email","role","type","name"];
if ("role" in data) data.splice(data.indexOf("role"),1); data.unshift("role");
data;