【问题标题】:Javascript: How can I swap elements of an array of objects (by reference, not index)?Javascript:如何交换对象数组的元素(通过引用,而不是索引)?
【发布时间】:2019-12-10 04:58:55
【问题描述】:

我有一个对象数组a=[ {v:0}, {v:1}, {v:2}, {v:3} ] ;

我没有 index 到数组中,但我确实有 引用 我想交换的 2 个值

s1=a[2] ; s2 = a[3] ;

如何使用这些引用来交换实际数组的元素?

[s1,s2] = [s2,s1] ; // only swaps s1 and s2, NOT elements of the array

// a is unchanged

【问题讨论】:

  • 在数组中查找这些对象的索引,然后按索引交换它们。
  • 您不能在不查找索引的情况下交换数组的元素。所做的只是交换s1s2 的引用。 a[2]a[3] 的引用仍将分别引用 {v:2}{v:3}

标签: javascript arrays pass-by-reference swap


【解决方案1】:

这是一个实用函数:

function swap(list, a, b) {
  var copy = list.slice();

  copy[list.indexOf(a)] = b;
  copy[list.indexOf(b)] = a;
  
  return copy;
}

// usage
var a =[ {v:0}, {v:1}, {v:2}, {v:3} ] ;

var result = swap(a, a[1], a[3]);

console.log(result); 
// [ {v:0}, {v:3}, {v:2}, {v:1} ]

请记住,由于您在数组中使用对象,因此您需要对该值的准确引用。例如。这不起作用:

var a =[ {v:0}, {v:1}, {v:2}, {v:3} ] ;

var result = swap(a, {v:1}, {v:3});

console.log(result); 
// [ {v:0}, {v:1}, {v:2}, {v:3} ]

这是检查数组中所有值的替代版本:

function swap(list, a, b) {
  return list.map(function(item) {
    if (item === a) {
      return b;
    } else if (item === b) {
      return a;
    }

    return item;
  });
}

【讨论】:

  • 如果a 在多个索引处包含特定引用,则只会交换找到的第一个索引处的引用。
  • 也是正确的,但我更喜欢不可变的方式
【解决方案2】:

这是一个单行,以防万一:

a.splice(a.indexOf(s2), 1, a.splice(a.indexOf(s1),1,s2)[0]);

【讨论】:

  • 请注意,这样做的好处是不需要复制任何东西
【解决方案3】:

JavaScript 中没有“按引用传递”。在大多数情况下,对象充当指针,而不是引用。

不幸的是,这意味着您需要找到对象的索引,然后使用这些索引交换它们:

// swap here, assumes the objects are really in the array
const s2index = a.indexOf(s2);
a[a.indexOf(s1)] = s2;
a[s2index] = s1;

根据您的用例,您应该检查对象是否确实在数组中。

【讨论】:

  • 您还应该检查对象是否被多个索引引用。
  • 这是否也交换了s1s2(连同数组元素)?
  • @briosheje 不,s1s2 仍然指的是同一个对象。这就是为什么我们不需要为其中一个对象使用通常的tmp,但我们确实需要一个用于索引之一的 tmp 变量。
  • @TomášZato 我可能错了,但据我了解,OP 想要交换数组中的引用和元素,但我可能错了。无论如何,这应该是公认的答案,不确定谁对所有答案投了反对票,但应该是公认的答案,因为它实际上解释了如何交换两个元素。
【解决方案4】:

如果您有参考资料,您可以通过Array.indexOf() 安全地检索索引:

a.indexOf(myReference) // returns the index of the reference or -1

然后,使用检索到的索引,您可以照常进行。

像这样:

let a = [{ v: 0 }, { v: 1 }, { v: 2 }, { v: 3 }];

const s1 = a[2];
const s2 = a[3];
console.log(a.indexOf(s1))

【讨论】:

  • 我必须亲眼所见才能相信 :)
  • @mplungjan :) 它实际上只适用于引用,如果您比较两个不同实例中的两个相同对象,它将不匹配
  • 谢谢!也许这应该是第二个问题?如果引用实际上是对两个不同的数组(而且我不知道哪些数组)怎么办?这种情况下还有希望吗?我将这些引用作为指针的概念正在崩溃。非常感谢...
  • 让我困惑的是,单独使用引用,我能够在没有任何 indexOf 的情况下更改数组中的各个属性,如 s1.v='new value' (它确实更改了数组元素),但我无法更改/替换 s1 引用的整个对象。
  • 但是我可以一一更改它们的属性,如 s1.v='new',这将更改数组元素的值。对吗?
猜你喜欢
  • 1970-01-01
  • 2018-05-23
  • 2020-04-10
  • 2016-08-25
  • 1970-01-01
  • 1970-01-01
  • 2016-04-10
  • 2017-11-10
  • 1970-01-01
相关资源
最近更新 更多