旋转数组元素的最佳方法,同时保持元素id的一致性

时间:2015-03-06 03:59:14

标签: javascript

给定一组对象:

var array = [
    { some_id: 0, name:'a' },
    { some_id: 1, name:'b' },
    { some_id: 2, name:'c' },
    { some_id: 3, name:'d' },
    { some_id: 4, name:'e' },
    { some_id: 5, name:'f' }
];

在更新移动的元素的some_id = 4值时,将some_id = 1的对象移动到位置some_id的最佳方法是什么,some_id的顺序变换后数组中的值保持不变?

例如,将some_id = 4移至some_id = 1后,您会获得:

array = [
    { some_id: 0, name:'a' },
    { some_id: 1, name:'e' },
    { some_id: 2, name:'b' },
    { some_id: 3, name:'c' },
    { some_id: 4, name:'d' },
    { some_id: 5, name:'f' }
];

基本上应该发生的事情是:

  1. 我们将{ some_id: 4, name:'e' }移至{ some_id: 1, name:'e' }
  2. 我们将{ some_id: 1, name:'b' }移至{ some_id: 2, name:'b' }
  3. 我们将{ some_id: 2, name:'c' }移至{ some_id: 3, name:'c' }
  4. 我们将{ some_id: 3, name:'d' }移至{ some_id: 4, name:'d' }
  5. 因此,我们只是旋转元素并更改some_id值。请注意,我们不会触及对象的任何其他属性。

3 个答案:

答案 0 :(得分:1)

我能想到的“在更新元素标识符时拖放元素”的“最佳”方式如下:



function move(key, src, to, array)                                              {
    var length   = array.length
    if (length === 0) return array
    var srcIndex = -1
    var toIndex  = -1
    var index    = 0

    loop: do switch (array[index][key])                                         {
        case src: srcIndex = index++; break loop
        case to:  toIndex  = index++; break loop                                }
    while (++index < length)

    if (index === length) return array

    if (srcIndex < 0) do if (array[index][key] === src)                         {
            srcIndex = index; break                                             }
        while (++index < length)
    else do if (array[index][key] === to)                                       {
            toIndex  = index; break                                             }
        while (++index < length)

    if (index === length) return array

    var step = toIndex < srcIndex ? 1 : -1
        src  = array[srcIndex]

    do                                                                          {
        to   = array[toIndex]
        array[toIndex] = src
        src[key] = toIndex
        toIndex += step
        src = to                                                                }
    while (toIndex !== srcIndex)

    array[toIndex] = src
    src[key] = toIndex
    return array                                                                }
&#13;
<script>
setTimeout(function () {
    var array = [
        { some_id: 0, name: 'a' },
        { some_id: 1, name: 'b' },
        { some_id: 2, name: 'c' },
        { some_id: 3, name: 'd' },
        { some_id: 4, name: 'e' },
        { some_id: 5, name: 'f' }
    ];

    print(move("some_id", 4, 1, array));

    print(move("some_id", 1, 4, array));

    function print(array) {
        alert("[\n" + array.map(function (obj) {
            return "    { some_id: " + obj.some_id +
                ", name: '" + obj.name + "' }";
        }).join(",\n") + "\n]");
    }
}, 0);
</script>
&#13;
&#13;
&#13;

这就是我在做的事情:

  1. 第一个loop找到srcIndextoIndex,无论哪个先出现。
  2. 如果我们找到srcIndextoIndex,如果它不是array的最后一个索引(这意味着我们也可能找到另一个索引),那么我们继续。否则我们会返回array
  3. 我们检查哪些索引仍未找到,我们循环查看剩余的元素以找到它。
  4. 如果我们无法找到第二个索引,那么我们会返回array。否则我们继续。
  5. 现在我们有两个索引,我们可以简单地重新排列最后一个循环中的元素。
  6. 希望有所帮助。

答案 1 :(得分:0)

您可以使用splice方法,该方法允许您将元素中的元素添加/删除到数组中。将索引1的元素移动到索引4:

element = arr.splice(1, 1);
arr.splice(4, 0, element);

您可以将这两者合并为一行:

arr.splice(4, 0, arr.splice(1,1));

这是拼接方法的W3Schools页面: http://www.w3schools.com/jsref/jsref_splice.asp

就更新ID而言,我循环遍历数组以将id与当前索引匹配(因为在您的示例中,您只是移动元素e而不是替换它与元素b):

arr.forEach( function(element, index) {
    element.some_id = index;
});

答案 2 :(得分:0)

这是AaditMShah答案的略微修改,重新格式化的版本

function move(key, src, to, array) {

    var srcIndex = -1, toIndex  = -1;

    for( var i = 0, l = array.length; i < l; i++ ) {
       switch(array[i][key]) {
           case src: 
              srcIndex = i; 
              break;
           case to: 
              toIndex  = i; 
              break;
       }

       if ( srcIndex > -1 && toIndex > -1 ) {
          break;
       }
    }

    if ( (srcIndex == -1 || toIndex == -1) || (srcIndex == toIndex )
      return array

    var step = toIndex < srcIndex ? 1 : -1
        src  = array[srcIndex]

    do {
        to   = array[toIndex]
        array[toIndex] = src
        src[key] = toIndex
        toIndex += step
        src = to
    } while (toIndex !== srcIndex);

    array[toIndex] = src
    src[key] = toIndex

    return array                                                                
}