在javascript中反转数组

Posted

技术标签:

【中文标题】在javascript中反转数组【英文标题】:reversing an array in javascript 【发布时间】:2017-09-15 03:25:56 【问题描述】:

我有一个名为 reverseArray 的 javascript 函数,它接受一个数组作为参数,并以相反的顺序返回一个与输入数组具有相同值的新数组。我想创建一个名为 reverseArryInPlace 的函数,它将输入数组的值更改为相反的顺序。

function reverseArray(inputArray) 
  var outputArray = [];
  for (var i = inputArray.length - 1; i >= 0; i--)
    outputArray.push(inputArray[i]);
  return outputArray;


function reverseArrayInPlace(inPlaceInputArray) 
  inPlaceInputArray = reverseArray(inPlaceInputArray);
  console.log('Inside reverseArrayInPlace: ' + inPlaceInputArray);
  return inPlaceInputArray;


var arrayValue = [1, 2, 3, 4, 5];
reverseArrayInPlace(arrayValue);
console.log('Outside reverseArrayInPlace: ' + arrayValue);
// Expected Value: [5, 4, 3, 2, 1]

这是我执行这段代码时得到的结果:

Inside reverseArrayInPlace: 5,4,3,2,1
Outside reverseArrayInPlace: 1,2,3,4,5

在 reverseArrayInPlace 函数中,arrayValue 变量已按预期反转。为什么我在reverseArrayInPlace函数外引用同一个变量时,又回到原来的顺序了?

【问题讨论】:

如果有功课就好了;它具有一个好问题的所有品质 您认为“InPlace”部分发生在您的代码中的什么位置? 您的reverseArrayInPlace() 不会就地 反转,它会创建一个新数组(这不是就地)。要反转 就地 交换原始数组中的元素,请不要创建新元素。 可以使用Array.reverse()函数 这是 Eloquent Javascript 书中的一个问题,但它不是家庭作业,因为我不在学校 【参考方案1】:

这里的根本问题是原语在 JavaScript 中是按值传递的。有关详细信息,请参阅以下问题:

Javascript by reference vs. by value

作为一个简单的例子,下面是一个试图改变传递给它的字符串的函数:

var outsideValue = 'foo'

function mutate(value) 
  value = 'fish'


mutate(outsideValue);
console.log(outsideValue);

但是,控制台输出是foo

发生这种情况是因为mutate 函数中的value 变量是一个在最初调用该函数时引用了outsideValue 的变量。当它在函数体中被赋予新值时,它只是改变value 变量来引用一个新的字符串。因此,outsideValue 未受影响。

查看此答案以获取在适当位置反转的示例:

https://***.com/a/43486686/249933

注意,它不会重新分配函数参数。

【讨论】:

基元是按值传递的,value 没有对 outsideValue 值的引用,它有一个值的副本。如果该值是一个引用(对一个对象),那么是的,它们都将引用同一个对象。但在这种情况下,该值是一个引用,而不是一个原始值。 ;-) 所以现在我明白了,通过放弃数组参数,我实际上并没有改变全局变量。但在示例答案中,我们改为重新分配数组参数的各个索引。当我们这样做时,为什么全局变量会发生变化? @AGP,这就是对象引用和原始值之间的区别。基元不能更改,只有保存它们的变量可以被覆盖(使用新值)。每次我将它们分配给一个新变量时,它们都会作为副本传递。对象作为引用传递。在幕后,内存中的地址在哪里找到这个对象。如果我更改对象的某些属性,对象本身就会更改,因此知道该对象的每个人都“具有”这种更改。【参考方案2】:

如果要原地反转,就必须原地反转。

function reverseArrayInPlace(array) 
  for (let i = 0, j = array.length - 1; i < j; i++, j--) 
    [array[i], array[j]] = [array[j], array[i]];


const a = [1,2,3,4,5];
reverseArrayInPlace(a);
console.log(a);

【讨论】:

好的,你能解释一下 [x,y]=[y,x] 语句中发生了什么吗? [a, b] = [b, a] 交换ab 的值,使用array destructuring assignment.. 为什么当你重新分配数组的各个索引时全局变量(a)发生了变化,但是当我重新分配整个数组时,全局变量没有改变?【参考方案3】:
function reverseArray(inputArray) 
  var outputArray = [];
  for (var i = inputArray.length - 1; i >= 0; i--)
    outputArray.push(inputArray[i]);
  return outputArray;


function reverseArrayInPlace(inPlaceInputArray) 
  inPlaceInputArray = reverseArray(inPlaceInputArray);
  console.log('Inside reverseArrayInPlace: ' + inPlaceInputArray);
  return inPlaceInputArray;

var arrayValue = [1, 2, 3, 4, 5];
**arrayValue = reverseArrayInPlace(arrayValue);**
alert('Outside reverseArrayInPlace: ' + arrayValue);
// Expected Value: [5, 4, 3, 2, 1]

//

您的代码是正确的,您只需替换一行并编写 arrayValue = reverseArrayInPlace(arrayValue); 代替 reverseArrayInPlace(arrayValue); 然后 arratValue 将打印期望值

【讨论】:

这不会原地反转。它将用 new 数组替换 arrayValue 的值。 然后我们需要添加新变量并打印它而不是 arrayValue 像: var reversedValue = reverseArrayInPlace(arrayValue);然后打印这个新值 alert('Outside reverseArrayInPlace: ' + reversedValue); 你没有完全理解in place的意思。 这很清楚。 AGP 想要在 arrayValue 变量中打印反转数组,您可以在他的代码和他提出的问题中看到它。使用这一行“arrayValue = reverseArrayInPlace(arrayValue);”肯定会解决他的问题。请再读一遍问题,你就会明白了。 @NEO——这不是 OP 想要的。您正在创建一个新数组 (var outputArray = []),然后将对它的引用分配给原始变量。原始数组对象仍然存在,没有改变,但现在可能已经准备好进行垃圾回收了。【参考方案4】:

正如其他人所说,数组是对象,因此它们是通过引用传递的。您必须修改原始数组,而不是创建新数组。

所以这是 reverseInPlace 的另一个版本,它使用 shift 从数组中删除最后一个元素,并使用 splice 将其插入新的地点:

function reverseInPlace(arr) 
  var i = arr.length;
  while (i--) 
    arr.splice(i, 0, arr.shift());
  


var arr = [1,2,3,4,5];
console.log('Before: ' + arr.join());

reverseInPlace(arr);
console.log('After:  ' + arr.join());

为了一些乐趣,您还可以利用 sort

注意:这只适用于某些浏览器,它依赖于内置的排序算法,该算法依赖于实现。

function reverseInPlace(arr) 
  arr.sort(() => 1);


var arr = [47, 95, 80, 62, 8, 34, 31, 17, 62, 17, 85, 72, 51, 20, 68, 60, 30, 84, 7, 34];
console.log('Before: ' + arr.join());

reverseInPlace(arr);
console.log('After : ' + arr.join());

【讨论】:

很遗憾,您的“有趣”版本不起作用。它取决于内部排序算法和调用排序函数的顺序。要查看此内容,请尝试Array.from(length: 100, _ =&gt; Math.floor(Math.random() * 100)).sort(() =&gt; 1) @torazaburo——它在 Firefox 38 中对我“有效”,(但在 IE 中失败)。 ;-) 我想知道这一点,很高兴确认我的怀疑是有根据的。 我认为这与浏览器根据数组的大小切换到不同的算法有关。

以上是关于在javascript中反转数组的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JavaScript 中反转数组,同时保留原始数组的原始值? [复制]

反转存储在 javascript 变量中的 JSON 数组

JavaScrip和Java一样吗?

好程序员分享JavaScrip数组去重操作实例小结

javascript反转数组

11中javascrip教程教不到的小技巧