Как отправить повторяющуюся строку / число в newArr по рекурсии? - PullRequest
0 голосов
/ 20 декабря 2018

как проверить дубликат числа / строки в массивах с помощью рекурсии, затем вставить их в newArr и передать уникальный номер / строку в newArrTwo

function rec(those) {
 let [unique, twin] = [ [], [] ];
 
};

console.log(rec([2, "str", "arr", "str", 2, "obj", "arg"]));
console.log(rec(["ref", "val", "val", "val", "el", "el"]));

желаемый результат - unique = ["arr", "obj", "arg"]; и twin = [2,"str"]

Ответы [ 3 ]

0 голосов
/ 20 декабря 2018

Попробуйте (объяснение здесь ):

 let twin = those.filter(( t={}, e=>!(1-(t[e]=++t[e]|0)) )); 
 let unique = those.filter(x=>!twin.includes(x)); 

function rec(those) {
 let t={};
 let twin = those.filter(( t={}, e=>!(1-(t[e]=++t[e]|0)) )); 
 let unique = those.filter(x=>!twin.includes(x)); 
  
 return [unique, twin];
};

console.log(JSON.stringify(rec([2, "str", "arr", "str", 2, "obj", "arg"])));
console.log(JSON.stringify(rec(["ref", "val", "val", "val", "el", "el"])));
0 голосов
/ 20 декабря 2018

Моя попытка:

function rec(array) {

  const result = array.reduce((result, current) => {
    if(result[0].indexOf(current) == -1) {
      result[0].push(current);
    }
    else {
      result[1].push(current);
    }
    return result;
  }, [[], []]);


  result[0] = result[0].filter((elem) => result[1].indexOf(elem) === -1);

  return result;

}
0 голосов
/ 20 декабря 2018

Обновление

Я неправильно прочитал спецификации изначально.Ниже этого раздела я подробно опишу несколько решений другой, но связанной проблемы.Вот решение для запрошенного:

const rec = (arr, uniqs = new Set, dups = new Set, [x, ...xs] = arr) => 
  arr.length == 0
  ? [[...uniqs], [...dups]]
  : uniqs.has(x) || dups.has(x)
    ? rec(xs, (uniqs.delete(x), uniqs), dups.add(x))
    : rec(xs, uniqs.add(x), dups)

console.log(rec([2, "str", "arr", "str", 2, "obj", "arg"]));
console.log(rec(["ref", "val", "val", "val", "el", "el"]));

Обратите внимание, что по сравнению с окончательным исходным ответом произошли два изменения:

  • Мы перешли на Набор для dups какну, с изменениями, необходимыми для этого.

  • Эта строка теперь удаляется из набора uniqs, а не просто передает его:

    ? rec(xs, (uniqs.delete(x), uniqs), dups.add(x))
    

Это фактически указывает на проблему API с Set.Это действительно полезно, что add возвращает набор.Жаль, что delete тоже так не делает.Хотя иногда может быть полезно возвращение логического значения, это довольно легко получить с помощью has.Это слишком поздно, чтобы исправить это, но это действительно позор.

Оригинальный ответ

Вот один из возможных подходов.Функции ES6, такие как параметры отдыха и параметры по умолчанию наряду с Symbol, обеспечивают довольно элегантную реализацию.

const None = Symbol()

const rec = ([x = None, ...xs], uniqs = [], dups = []) => 
  x == None 
  ? [uniqs, dups]
  : uniqs.includes(x)
    ? rec(xs, uniqs, dups.concat(x))
    : rec(xs, uniqs.concat(x), dups)

console.log(rec([2, "str", "arr", "str", 2, "obj", "arg"]));
console.log(rec(["ref", "val", "val", "val", "el", "el"]));

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

Использование Symbol Вот интересный способ объединить наш разброс входного массива в голову и хвост и все же позволить нам проверить, если он пуст.Альтернативное средство показано ниже.

const rec = (arr, uniqs = [], dups = [], [x, ...xs] = arr) => 
  arr.length == 0 
  ? [uniqs, dups]
  : uniqs.includes(x)
    ? rec(xs, uniqs, dups.concat(x))
    : rec(xs, uniqs.concat(x), dups)

console.log(rec([2, "str", "arr", "str", 2, "obj", "arg"]));
console.log(rec(["ref", "val", "val", "val", "el", "el"]));

Эта версия выглядит немного менее чистой, чем оригинал, но не требует определения вспомогательного символа только для проверки на пустоту.

Есть еще что-тонеправильно с этим;это может иметь проблемы с производительностью.Поскольку для каждого элемента мы должны вызывать O(n) includes, общее решение выглядит примерно так: O(n^2), в зависимости от соотношения уникальных значений для дубликатов.Это может не быть проблемой, и я могу исправить это только в одном из двух сценариев:

  • Я протестировал и обнаружил, что этот код является реальным узким местом в моем приложении
  • У меня есть более производительная альтернативная версия, которая жертвует небольшой ясностью кода.

В этом случае у меня есть такая версия:

const rec = (arr, uniqs = new Set(), dups = [], [x, ...xs] = arr) => 
  arr.length == 0
  ? [[...uniqs], dups]
  : uniqs.has(x)
    ? rec(xs, uniqs, dups.concat(x))
    : rec(xs, uniqs.add(x), dups)

console.log(rec([2, "str", "arr", "str", 2, "obj", "arg"]));
console.log(rec(["ref", "val", "val", "val", "el", "el"]));

(Мы также могли бы использовать альтернативу Symbol в этой версии.)

Здесь мы переключаемся на использование Set, которое точнотип данных, предназначенный для работы с коллекцией уникальных элементов.Это требует небольшого развертывания набора с [...uniqs] - альтернативно Array.from(uniqs) - но это очень незначительное увеличение сложности.Остальные изменения касаются переключения с массива на набор.

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