2016-11-07 2 views
3

Были и другие вопросы по этой проблеме, но я хотел бы знать, почему мой код не отменяет данный массив. Примечание. Я очень новичок в кодировании, просто учась и стараюсь практиковать для личного интереса.reverseArrayInPlace() не работает должным образом

В книге Eloquent Javascript нам предлагается написать две различные функции, которые меняют массив. Первая функция, reverseArray, должна выводить новый массив, который является обратным заданному. Это достаточно легко.

Вторая функция, reverseArrayInPlace, должна изменить данный массив, чтобы он был обратным. Предполагается, что просто использование первой функции, а затем присвоение ее значения первому массиву является «обманом». Кроме того, мы не можем использовать обратный метод.

Вот моя попытка, и я не могу понять, почему он не работает:

var reverseArrayInPlace = function(anArray) { 
    for (var i = 1; i < anArray.length; i++) { 
     anArray = anArray.slice(i, i+1).concat 
     (anArray.slice(0,i)).concat(anArray.slice(i+1)); 
    } 
} 

Примечание: мне не нравится, как я написал эту функцию, но тем не менее я не могу решить, почему это не работает.

Вот тестовый код в книге и целевой вывод:

var arrayValue = [1, 2, 3, 4, 5]; 
reverseArrayInPlace(arrayValue); 
console.log(arrayValue); 
// → [5, 4, 3, 2, 1] 

Намек в книге говорит:

"Хитрость заключается в том, чтобы поменять местами первые и последние элементы, затем второй и второй-последний и т. д. Вы можете сделать это, зациклив на половину длины массива (используйте Math.floor для округления вниз - вам не нужно касаться среднего элемента в массиве с помощью нечетная длина) и обменивание элемента в позиции i с единицей в позиции array.length - 1 - i. Вы можете использовать локальную переменную, чтобы ненадолго удерживать одну из элементы, замените это зеркальным изображением, а затем поместите значение из локальной переменной в место, где раньше было зеркальное изображение. "

мне не нравится моя идея, но мне нравится этот намек еще меньше. Есть ли что-то более в духе изменения массива„на месте“с идеей Намек, чем у меня?

Спасибо за . помощь И опять же, мы не можем просто использовать то, что называется .reverse на данном массиве

+0

это тело для цикла одной строки кода? это проблема двойного '.concat concat' от первой линии тела ко второй? –

+0

Вы проверили консоль? (Http://stackoverflow.com/documentation/javascript/185/hello-world/714/using-console-log) В вашем коде имеется ряд ошибок. Но чтобы добраться до корня проблемы, вы не можете просто создать массив чисел (это то, что делают 'slice' и' concat'), если вы хотите изменить существующий массив. –

+0

Каждый вызов '.slice()' будет создавать новый массив. Похоже, это довольно далеко от духа, делающего разворот на месте. – Pointy

ответ

-2

Это код автор ищет:.

var reverseArrayInPlace = function(anArray) { 
    for (var i = 0; i <= anArray.length/2; i++) { 
    var t = anArray[i]; 
    anArray[i] = anArray[anArray.length - 1 - i]; 
    anArray[anArray.length - 1 - i] = t; 
    } 
} 

Edit: следующие предложения в комментариях , вот что делает эта функция: она реализуется метод из подсказки: замена элементов парами. 1-й и последний, затем 2-й и 2-й, и т. Д.

+2

Не просто раздавайте бесплатный код. Объясните * почему * этот код работает. –

+0

@MikeC В подсказке в книге даются точные пошаговые инструкции. То, что делает код, очевидно, если вы посмотрите на него и подсказку. –

+1

Видимо, OP не очевидно. Независимо от того, ваш ответ должен стоять сам по себе без помощи книги и должен * объяснить * решение. –

0

Я вижу две ошибки:

Первое, что вы удвоили concat вызов:

var reverseArrayInPlace = function(anArray) { 
    for (var i = 1; i < anArray.length; i++) { 
     anArray = anArray.slice(i, i+1).concat // two concats! one here and one on next line 
     concat(anArray.slice(0,i)).concat 
     (anArray.slice(i+1)); 
    } 
} 

Другая ошибка в том, что вы ничего не возвращает. Скорректированная функция выглядит так:

var reverseArrayInPlace = function(anArray) { 
    for (var i = 1; i < anArray.length; i++) 
     anArray = 
     anArray 
     .slice(i, i + 1) 
     .concat(anArray.slice(0, i)) 
     .concat(anArray.slice(i + 1)); 

    return anArray; 
}; 

Обратите внимание, что это даже не близко к развороту «на месте». Этот код будет делать много промежуточных массивов, прежде чем перейти к окончательному результату.Реальный разворот на месте будет сильно отличаться, возможно, обмениваясь элементами.

В зависимости от требований одна из возможностей может заключаться в замене элементов с конца на элементы с начала, остановки в середине. Обмен часто будет состоять из использования переменной temp, которая также может считаться нарушением «на месте».

Чтобы сделать это полностью на месте, даже без переменной темпа, можно использовать трюк XOR для замены элементов. Это будет работать только с числами, но не такими вещами, как объекты. Вы также не хотите обменивать центральный элемент (если он есть) таким образом, так как вы его обнулите.

// tricky way to swap two elements (assumes front != back) 
anArray[front] ^= anArray[back]; 
anArray[back] ^= anArray[front]; 
anArray[front] ^= anArray[back]; 
+0

Это не изменяет исходный массив. Он создает новый массив. –

+0

@MikeC да, это не «разворот на месте», но вопрос был «почему этот код не работает». –

+0

Справа. Он не отменяет массив на месте. Это часть, которая не работает. –

1

Хотя это не кратчайшее решение, я попытался написать его, чтобы его было легко понять.

В основном мы создаем 2 указателя указателя в массиве слева и справа, слева от начала, начиная с первого элемента, а затем справа от последнего.

Потому что нам не нужно обменивать середину простой проверки слева < прямо внутри цикла while остановит его до того, как он туда попадет.

Затем мы используем tmp var для использования в качестве временного заполнителя при замене элементов, после чего мы можем увеличить левый и уменьшить указатели указателей справа.

Чтобы сделать это в месте замены, мы используем методы доступа массив индексов, используя [] вместо среза и т.д.

var reverseArrayInPlace = function(anArray) { 
 
    var left = 0, right = anArray.length - 1, tmp; 
 
    while (left < right) { 
 
    tmp = anArray[left]; 
 
    anArray[left] = anArray[right]; 
 
    anArray[right] = tmp;  
 
    left ++; 
 
    right --; 
 
    } 
 
} 
 

 
var a = [1,2,3,4,5]; 
 

 
reverseArrayInPlace(a); 
 

 
console.log(a);

0

Ваш код работает, когда вы гуляете до конец массива (array.length + 1) и когда вы возвращаете новый массив.

var numbers = [1, 2, 3, 4, 5, 6]; 
 

 
var reverseArrayInPlace = function(arr) { 
 
    for (var i = 1; i < arr.length + 1; i++) { 
 
    arr = arr.slice(i, i + 1).concat(arr.slice(0, i)).concat(arr.slice(i + 1)); 
 
    } 
 
    return arr; 
 
} 
 

 
var r = reverseArrayInPlace(numbers); 
 
console.log(r);

Но речь идет о движении задним ходом используется массив с другихкритериев.


Подсказка в книге дает вам практически решение.

Это о

  • своп
  • половину длины массива
  • массива.длина - 1 - я

подкачки является

var n = [4, 9]; 
 
var temp = n[0]; // Assign left to a temporary (locale) variable for a "briefly hold" 
 
n[0] = n[1]; // Assign right to left 
 
n[1] = temp; // Assign the temporary variable (left) to right 
 
console.log(n);

Половина длина массива

var half = Math.floor(arr.length/2); 

с Math.floor. Именно там, чтобы поймать также массив с нечетного длины

Math.floor(7/2) -> 3 

В общей сложности

var numbers = [1, 2, 3, 4, 5]; 
 

 
function reverseArrayInPlace(arr) { 
 
    var half = Math.floor(arr.length/2); 
 
    for (var i = 0; i < half; i += 1) { 
 
    // Swap start 
 
    var temp = arr[i]; 
 
    arr[i] = arr[arr.length - 1 - i]; 
 
    arr[arr.length - 1 - i] = temp; 
 
    // Swap end 
 
    } 
 
} 
 

 
reverseArrayInPlace(numbers); 
 
console.log(numbers);

Смежные вопросы