2017-01-02 9 views
1

Я не получаю ожидаемых результатов при попытке это reduce в JavaScript:JavaScript-массив уменьшает длину сумм суб-массивов - почему это не работает?

let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; 

x.reduce((a,b) => a.length + b.length, []); 

Простой, правильно? Вот что я ожидаю, шаг за шагом:

---------------------------------------------------------------- 
| callback | a (accumulator) | b (currentValue) | return value | 
---------------------------------------------------------------- 
| 1st run | 0    | 3    | 3   | 
---------------------------------------------------------------- 
| 2nd run | 3    | 3    | 6   | 
---------------------------------------------------------------- 
| 2nd run | 6    | 3    | 9   | 
---------------------------------------------------------------- 

Что я на самом деле получаю? NaN. На английском языке, если я правильно понимаю вещи, итератор сначала смотрит на исходное значение, которое я ему даю (пустой массив как второй аргумент reduce), и это представлено аргументом a. Мой код показывает простой .length на оба добавляемых аргумента. Где я здесь не так?

+1

Входы представляют собой массивы, а не числа, вы замаскируете это в своей диаграмме. Первое значение 'a' -' [] ', а не' 0', поэтому 'a.length' работает. Вернув номер, вы загружаете номер в следующую итерацию и вызываете на нем '.length', что явно не является вашим намерением. – meagar

+0

@meagar Yup, только что понял, что смотрит на код Уайта ниже. Спасибо! –

+1

Если вы намерены суммировать длину массивов, вы можете «правильно отобразить» и «уменьшить»: «x.map (a => a.length) .reduce ((a, b) => a + b) ' – meagar

ответ

-1

код заостренный в выше (на самом деле не возвращать 9, как предполагаемый) заставил меня этого рабочего раствора:

let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; 
x.reduce((a,b) => a + b.length, 0); 

Скудные также отметил в комментариях, что это классический случай для map/reduce комбо как таковой (гораздо изящнее решение):

let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; 
x.map(a => a.length).reduce((a,b) => a + b); 
+3

'a' никогда не будет уменьшаться массивом при установке начального начального значения как нуля и никогда не возвращать массив из обратного вызова. Смотрите https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce – charlietfl

+0

Решение Meager является ошибочным, потому что ему не хватает начального значения и поэтому терпит неудачу, если в массиве нет элементов, хотя, вероятно, это должен быть допустимый ввод, возвращающий ноль. –

+0

@torazaburo Я поставил назначение переменной в решении скудного, чтобы хотя бы показать его для этого конкретного экземпляра. Но точка взята. –

1

API .reduce() API ожидает, что ваша функция обратного вызова вернет значение аккумулятора (в вашем случае значение начинается с []). Ваш обратный вызов просто возвращает значение.

Чтобы сделать код работу, вам нужно что-то вроде:

x.reduce((a,b) => { a.push(a.length + b.length); return a; }, []); 

Теперь, если то, что вы действительно хотите это сумма длин массивов, то вы не хотите все равно накапливаются в массив; вам нужна простая сумма. Вместо того, чтобы аккумулятор представляет собой массив, то он просто должен быть номер:

var sum = x.reduce(((sum, array) => sum + array.length), 0); 

Начать с нуля, и каждый вызов функции добавляет длину массива на сумму.

+0

Можете ли вы опубликовать корректировку кода, чтобы показать пример? –

+1

@ TheQodesmith только что сделал :) – Pointy

+0

Ах, я вижу. Поэтому в моем случае, поскольку я накапливаю массивы, массив нужно вернуть, чтобы продолжить повторение, чтобы быть последовательным. –

5

Я думаю, что это то, что вы пытаетесь сделать (переменные переименованы для ясности):

let x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; 

x.reduce((acc,element) => acc + element.length, 0); 

Вот как это будет происходить шаг за шагом:

-------------------------------------------------------------- 
| callback | acc | element | element.length | return value | 
-------------------------------------------------------------- 
| 1st run | 0 | [1, 2, 3] | 3    | 3   | 
-------------------------------------------------------------- 
| 2nd run | 3 | [4, 5, 6] | 3    | 6   | 
-------------------------------------------------------------- 
| 3rd run | 6 | [7, 8, 9] | 3    | 9   | 
-------------------------------------------------------------- 
0

В качестве альтернативы использованию reduce, сплющить массив и принять длину результата.

function flatten(a) { return [].concat(...a); } 
 

 
const x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; 
 
const length = flatten(x).length; 
 

 
console.log(length);

Реализация flatten выше для массивов, которые имеют глубину одного или двух. Расширьте/замените его по мере необходимости для более глубоко вложенных массивов.