2015-08-10 4 views
3

Я новичок в javascript, и у меня есть немного проблем, изучая его сам из веб-уроков. Пожалуйста, помогите мне решить проблему ниже.Использование javascript array.reduce для удаления дубликатов

Проблема:

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

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

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

Используйте только Array.reduce, чтобы решить эту проблему! Это то, что ваше решение должно выглядеть следующим образом:

function unite(arr1, arr2, arr3) { 
    return arr1; 
} 

unite([1, 2, 3], [5, 2, 1, 4], [2, 1]); 

Я не могу понять, как я могу использовать сократить здесь. Все интернет-примеры настолько легки по сравнению с этим. https://www.airpair.com/javascript/javascript-array-reduce http://adripofjavascript.com/blog/drips/boiling-down-arrays-with-array-reduce.html

Мое неправильное решение:

function arrayDiff(resultArray, element){ 
    var idx = anotherArray.indexOf(element); 
    if(idx != -1){ 
     resultArray.push(element); 
     return resultArray; 
    } 
} 

function unite(arr1, arr2, arr3) { 
    var arr = []; 
    var r1 = arr1.reduce(arrayDiff); 
    var r2 = arr2.reduce(arrayDiff); 
    var r3 = arr3.reduce(arrayDiff); 
    arr.concat(r1).concat(r2).concat(r3); 
    return arr; 
} 


r = unite([1, 2, 3], [5, 2, 1, 4], [2, 1]); 
console.log(r); 

Ошибка: ReferenceError: AnotherArray не определен

+0

хорошо, это потому, что 'anotherArray' не определен. На что должна ссылаться эта переменная? – zerkms

+0

Да, 'anotherArray' не определен. Чего вы ожидали? – Bergi

+0

@Bergi - Я только что увидел здесь пример - 'var sum = [1, 2, 3] .reduce ( function (total, num) {return total + num}, 0);'. Похоже, что итоговая переменная. Итак, я последовал этому примеру и сделал anotherArray в качестве моей переменной result. Это смущает. – stack1

ответ

1

Я думаю, что вы хотите проверить, является ли element уже в resultArray, а не в какой-то anotherArray. При том, что он может работать любопытное:

function arrayDiff(resultArray, element){ 
    var idx = resultArray.indexOf(element); 
    if (idx == -1) { // add only when not already found in the result array 
     resultArray.push(element); 
    } 
    return resultArray; // always return the resultArray even if we didn't add to it 
} 

function unite(arr1, arr2, arr3) { 
    var r0 = []; 
    var r1 = arr1.reduce(arrayDiff, r0); // supply some start accumulator argument 
    var r2 = arr2.reduce(arrayDiff, r1); // and pass the results through so that 
    var r3 = arr3.reduce(arrayDiff, r2); // duplicates are filtered amongst all arrays 
    return r3; 
} 
+0

Не понял - поставьте некоторый аргумент аккумулятора начала – stack1

+0

@ stack1: Вы знаете, что [второй параметр 'reduce'] (https: //developer.mozilla .org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce), не так ли? – Bergi

+0

@ stack1 btw, это решение не решает вашу оригинальную задачу (но это хорошо, теперь у вас есть шанс ее улучшить) – zerkms

5

Для обработки нескольких параметров массива, вы можете использовать arguments. Благодаря этому ваша функция может принимать параметры N, она является более общей.

Затем вы можете поместить все параметры вашего массива и начать с уменьшить ваши данные. Когда вы уменьшите наш массив, вы создадите новый массив, исключив избыточные данные. Итак, вы начнете с пустым массивом, и вы заполните его через процесс сокращения.

function unite(){ 
    //Flat array arguments, then process to reduce data 
    return [].concat.apply([], arguments).reduce(function(result, current){ 
     //If my result array doesn't get current element 
     return result.indexOf(current) === -1 
     //concat current element to result and return it 
     ? result.concat(current) 
     //Otherwise, just return actual result array 
     : result; 
    }, []); 
    } 

    var array = unite([1,2], [1,6,2,3], [4,5]); 

    console.log(array); 
    //[1,2,6,3,4,5] 

EDIT 06/02/2017:

Теперь вы можете использовать spread operator для того, чтобы обрабатывать несколько параметров, с помощью уничтожения того назначения, например. Кроме того, мы можем улучшить производительность, используя операцию indexOf() с побитовым оператором ~.

function unite(...data) { 
    return [].concat.apply([], data).reduce((result, current) => { 
    return ~result.indexOf(current) 
    ? result 
    : result.concat(current) 
    }, []); 
} 

console.log(unite([1,2,3], [1, 4, 4, 5, 6])); 
+0

Я в значительной степени написал то же самое решение, но я просто буду голосовать за вас :) – Peter

0

Это мое решение, намного чище/короче:

function uniteUnique(arr) { 
    var args = Array.from(arguments); 
    var test = []; 

    for (var i = 0; i < args.length; i++) { 
    for (var j = 0; j < args[i].length; j++) { 
     if (test.indexOf(args[i][j]) == -1) {  
      test.push(args[i][j]); 
     } 
    } 
    } 

    return test; 
} 

uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]); 
Смежные вопросы