2015-12-03 3 views
0

У меня есть функция fill определена здесь:Заполнения пустой части массива, функциональный способ Javascript

/* 
    Takes an Array `array` containing null values, and return a copy of that array, filled with the values in `nArray`: 

    Usage: 
    fill(
     [1, 2, 3], 
     [null, 4, null, 5, null] 
    ) 
    // => [1, 4, 2, 5, 3]; 
*/ 
const fill = (nArray, array) => { 
    let i = 0; 
    return array.map((e) => !e ? nArray[i++] : e); 
} 

Счетчик i определяется с let и не является неизменным, так что этот код не является чисто функциональным , Как бы вы создали эту функцию, чтобы она стала чисто функциональной?

+2

Этот счетчик не виден во внешнем мире, поэтому его никто не заботится. Ваш код является читаемым, функциональным и эффективным по мере его поступления. – Bergi

ответ

1

Просто сделать использование shift:

const fill = (nArray, array) => { 
    return array.map((e) => !e ? nArray.shift() : e); 
} 

EDIT:

Заметим также, что вы должны проверить, что nArray не является пустым, например:

(!e && nArray.length > 0) ? nArray.shift() : e 
+0

Я должен был подумать об этом! благодаря ! –

+2

Ну, это еще хуже, теперь вы мутируете ввод функции. Не делай этого. Нельзя назвать это «функциональным» вообще, а «чисто» еще меньше. – Bergi

+0

@ Берги хорошо, ты прав ... Но я не могу удалить свой ответ, так как он был принят! 'shift' снова скрывает мутацию :-) –

0

Если вы не ожидаете, что map будет какой-то странной функцией (не типичный Array.prototype) w здесь этот нечистый обратный вызов вызовет хаос, ваш код будет полностью прекрасен. i не наблюдается из внешнего мира, что делает вашу функцию чистой.

Если вы хотите, чтобы избежать все мутации любой цены, вы должны в основном идете для рекурсивного подхода:

const fill = (nArray, array) => 
    array.length 
    ? array[0] 
    ? [array[0]].concat(fill(nArray, array.slice(1))) 
    : [nArray[0]].concat(fill(nArray.slice(1), array.slice(1))) 
    : [] 

(который ужасно неэффективен, конечно, учитывая отсутствие в JavaScript списков минусов)

Вы также можете использовать более декларативную реализацию одной и той же вещи:

const fill = (nArray, array) => { 
    if (!array.length) return []; 
    const [a, ...as] = array; 
    if (a) return [a, ...fill(nArray, as)]; 
    const [b, ...bs] = nArray; 
    return [b, ...fill(bs, as)]; 
}; 
Смежные вопросы