将数组元素从一个数组位置移动到另一个位置
Posted
技术标签:
【中文标题】将数组元素从一个数组位置移动到另一个位置【英文标题】:Move an array element from one array position to another 【发布时间】:2011-07-15 11:14:36 【问题描述】:我很难弄清楚如何移动数组元素。例如,给定以下内容:
var arr = [ 'a', 'b', 'c', 'd', 'e'];
如何编写函数将'd'
移动到'b'
之前?
还是在'c'
之后'a'
?
移动后,其余元素的索引应更新。这意味着在移动后的第一个示例中,
arr = ['a', 'd', 'b', 'c', 'e']
这看起来应该很简单,但我无法理解它。
【问题讨论】:
使用 ES6const changeValuePosition = (arr, init, target) => [arr[init],arr[target]] = [arr[target],arr[init]]; return arr
这只是交换init
和target
的元素。
【参考方案1】:
我认为最好的方法是为数组定义一个新属性
Object.defineProperty(Array.prototype, 'move',
value: function (old_index, new_index)
while (old_index < 0)
old_index += this.length;
while (new_index < 0)
new_index += this.length;
if (new_index >= this.length)
let k = new_index - this.length;
while ((k--) + 1)
this.push(undefined);
this.splice(new_index, 0, this.splice(old_index, 1)[0]);
return this;
);
console.log([10, 20, 30, 40, 50].move(0, 1)); // [20, 10, 30, 40, 50]
console.log([10, 20, 30, 40, 50].move(0, 2)); // [20, 30, 10, 40, 50]
【讨论】:
【参考方案2】:此方法将保留原始数组,并检查边界错误。
const move = (from, to, arr) =>
to = Math.max(to,0)
from > to
? [].concat(
arr.slice(0,to),
arr[from],
arr.filter((x,i) => i != from).slice(to))
: to > from
? [].concat(
arr.slice(0, from),
arr.slice(from + 1, to + 1),
arr[from],
arr.slice(to + 1))
: arr
【讨论】:
【参考方案3】:在您的示例中,因为是string
的数组,我们可以使用排名对象对字符串数组重新排序:
let rank = 'a': 0, 'b': 1, 'c': 2, 'd': 0.5, 'e': 4 ;
arr.sort( (i, j) => rank[i] - rank[j] );
我们可以使用这种方法编写一个move
函数来处理字符串数组:
function stringArrayMove(arr, from, to)
let rank = arr.reduce( (p, c, i) => ( p[c] = i, p ), ( ) );
// rank = 'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4
rank[arr[from]] = to - 0.5;
// rank = 'a': 0, 'b': 1, 'c': 2, 'd': 1.5, 'e': 4
arr.sort( (i, j) => rank[i] - rank[j] );
// arr = [ 'a', 'd', 'b', 'c', 'e' ];
let arr = [ 'a', 'b', 'c', 'd', 'e' ];
stringArrayMove(arr, 3, 1);
console.log( JSON.stringify(arr) );
然而,如果我们想要排序的是一个对象数组,我们可以将排名作为每个对象的新属性引入,即
let arr = [ value: 'a', rank: 0 ,
value: 'b', rank: 1 ,
value: 'c', rank: 2 ,
value: 'd', rank: 0.5 ,
value: 'e', rank: 4 ];
arr.sort( (i, j) => i['rank'] - j['rank'] );
我们可以使用Symbol
隐藏此属性的可见性,即它不会显示在JSON.stringify
中。我们可以在objectArrayMove
函数中概括这一点:
function objectArrayMove(arr, from, to)
let rank = Symbol("rank");
arr.forEach( (item, i) => item[rank] = i );
arr[from][rank] = to - 0.5;
arr.sort( (i, j) => i[rank] - j[rank]);
let arr = [ value: 'a' , value: 'b' , value: 'c' , value: 'd' , value: 'e' ];
console.log( 'array before move: ', JSON.stringify( arr ) );
// array before move: ["value":"a","value":"b","value":"c","value":"d","value":"e"]
objectArrayMove(arr, 3, 1);
console.log( 'array after move: ', JSON.stringify( arr ) );
// array after move: ["value":"a","value":"d","value":"b","value":"c","value":"e"]
【讨论】:
【参考方案4】:如果对象是嵌套的:
let array = ['a', 'b', 'c', 'd', 'e'];
let existingElement = JSON.parse(JSON.stringify(array[3]));
array.splice(1, 0, existingElement);
array.splice(4, 1);
console.log(array)
【讨论】:
以上是关于将数组元素从一个数组位置移动到另一个位置的主要内容,如果未能解决你的问题,请参考以下文章
以 HTML 无序列表的形式将数组元素从 html 表移动到另一个数组
是否可以使用淡入淡出将 ui 元素从一个位置移动到另一个位置?