JavaScript 将数组项移到前面

我想检查一个数组是否包含 "role"。如果是这样,我想将 "role"移到数组的前面。

var data= ["email","role","type","name"];
if ("role" in data) data.remove(data.indexOf("role")); data.unshift("role")
data;

在这里,我得到了结果:

["role", "email", "role", "type", "name"]

我该怎么补救?

144582 次浏览

我的第一反应是:

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

修改,整理一下:

if (data.indexOf('role') > 0) {
data.splice(data.indexOf('role'), 1);
data.unshift('role');
}

参考文献:

  1. in运算符是关于属性的,而不是关于数组中的项。
  2. If-block 中的两个(!)语句周围缺少大括号
  3. 我不确定您正在使用的 .remove()函数是否采用了某个项的索引。

您可以对数组进行排序,并指定值 "role"位于所有其他值之前,并且所有其他值都是相等的:

var first = "role";
data.sort(function(x,y){ return x == first ? -1 : y == first ? 1 : 0; });

演示: http://jsfiddle.net/Guffa/7ST24/

var i = -1;
while (i < data.length) {
if (data[i] === "role") {
data.splice(i, 1);
break;
}
i++;
}
data.unshift("role");

indexOf只有有限的浏览器支持,不能被 IE7-8识别。因此,如果我是你,我不会使用它,即使以牺牲几行代码的简洁性为代价。您还需要在“ unshift”语句的末尾加上分号。Splice ()的第一个参数指定开始删除元素的索引,第二个参数指定要删除的参数数量。

var data= ["email","role","type","name"];


data.splice(data.indexOf("role"), 1);
data.unshift('role');
var data= ["email","role","type","name"];
if ("role" in data) data.splice(data.indexOf("role"),1); data.unshift("role");
data;

在我看来,ES6中最干净的解决方案是:

let data = ["email","role","type","name"];
data = data.filter(item => item !== "role");
data.unshift("role");
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]

如果不想更改现有数组,可以使用过滤器方法的 ES6解构来创建一个新副本,同时维护其他项的顺序。

const data = ["email", "role", "type", "name"];
const newData = ['role', ...data.filter(item => item !== 'role')];

与@Tandroid 的回答类似,但它有一个更普遍的解决方案:

const putItemsFirst = ({ findFunction, array }) => [
...array.filter(findFunction),
...array.filter(item => !findFunction(item)),
];

可以像这样使用

putItemsFirst({
array: ["email","role","type","name"],
findFunction: item => item === 'role',
})

我最后用的就是类似的东西,

如果你有一个对象数组,你可以通过拼接和压入来移动开始索引。Splice 将原始数组替换为从所需索引开始的数组部分,并返回它删除的部分(索引前的内容)。

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

要检查数组中是否存在项,应该使用 .includes()而不是 in(如前所述,in用于对象中的属性)。

这个函数可以完成您所需要的任务: (将项目从它所在的位置移除并读取 前面)


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

如果需要,这里有一个不变的解决方案:

      const newData = [
data.find(item => item === 'role'),
...data.filter(item => item !== 'role'),
],

使用 loash 排序。如果该项是 role,则将首先对其进行排序,否则将第二次进行排序。如果没有 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>

你可以取支票的增量,最上面是想要的值。

var data = ["email", "role", "type", "name"];


data.sort((a, b) => (b === 'role') - (a === 'role'));


console.log(data);

我会选择 ES6的解决方案。它不会改变原始数组(考虑到它不是嵌套的) ,不会遍历数组(过滤器) ,并且不仅仅限于第0个索引来移动数组项。

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' ]

只是想把这个放在这里,因为根据其他评论 Guffa 的答案似乎正在获得牵引力,最后的第三个-这是其中一个负面评论的答案是没有必要的。同时使用箭头函数使它看起来更简洁。

此外,它很容易扩展到处理对象数组。

const first = "role";
data.sort((x, y) => first === x ? -1 : first === y)

我相信这也可以解决数组其他部分受到影响的问题。当 sort 函数返回一个小于0(first = = = x)的数字时,元素将移动到 Array 的开始,当它返回0(first!当一个数字大于0(first = = y)时,x 将移动到 Array 的末尾,所有这些都与 x 和 y 有关。因此,当 x 和 y 都不等于所需的第一个元素(或者对象排序时它的标识符)时,这两个元素就不会相互移动。

对于一个物体:

const unsorted = [{'id': 'test'}, {'id': 'something'}, {'id': 'else'}];
const first = 'something';
const sorted = unsorted.sort((x,y) => x['id'] === first ? -1 : y['id'] === first);

一个可重用的 ES6/Type 脚本解决方案:

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"))

广义的俏皮话:

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"]

data.unshift(data.splice(data.indexOf('role'), 1)[0])

data.indexOf('role')将在数组中找到“ role”的索引,然后将原始数组拼接起来以删除“ role”元素,该元素使用 unshift 添加到数组的开头

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'))

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))
function unshiftFrom(arr, index) {
if (index > -1 && index < arr.length) {    // validate index
var [itemToMove] = arr.splice(index, 1)
arr.unshift(itemToMove)
}
return arr   // optional
}

我的解决方案有点不同,因为它改变了原始数组,而不是创建一个新的数组。

它将把给定的项目移动到数组的开始位置,并将先前在开始位置的项目移动到请求项目的位置。

function moveElementToStart<T>(items: T[], item: T) {
const itemIndex = items.indexOf(item);


// Item is not found or it is already on start
if (itemIndex === -1 || itemIndex === 0) return;


// Get item that is currently at start
const currentItemAtStart = items[0];
  

// Swap this item position with item we want to put on start
items[0] = item;
items[itemIndex] = currentItemAtStart;
}

在我看来,这是最可读的方法。

array.sort((a, b) => (a === value && -1) || (b === value && 1) || 0)

//we can do this from scratch


let tempList=["person1","person2","person3"];
let result=[];
//suppose i need to move "person2" to first place
let movableValue=null;
let query="person2"; //here you could use any type of query based on your problem


tempList.map((e)=>{
if(e!==query){
result.push(e);
}else if(e===query){
movableValue=e;
}
})


if(movableValue!==null){
result.unshift(movableValue);
}


console.log(result)

)