Распечатайте все пути к листам древовидного массива списков и соедините соответствующие значения в пути с особыми условиями

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

inputArr =  [
             ["1", "p"], 
             ["1.1", "q"], 
             ["1.2", "a"], 
             ["1.2", "b"], 
             ["1.2", "c"], 
             ["1.2.1", "d"], 
             ["1.2.2", "4"], 
             ["1.2.2.1", "5"], 
             ["1.3", "6"], 
             ["1.4x", "7"], 
             ["2", "8"], 
             ["2.1", "9"], 
             ["2.2", "10"], 
             ["2.2.1x", "11"],
             ["2.2.2", "12"],
             ["3", "13"], 
             ["4", "14"]
            ];

Ожидаемый результат:

outputArr = [
             ["1.1", "p,q"], 
             ["1.2.1", "p,a,b,c,d"], 
             ["1.2.2.1", "p,a,b,c,4,5"], 
             ["1.3", "p,6"], 
             ["1.4x", "7"], // not "p,7", because key has a tailing 'x' 
             ["2.1", "8,9"], 
             ["2.2.1x", "11"], //not "8,10,11", because key has a tailing 'x'
             ["2.2.2", "8,10,12"],
             ["3", "13"], 
             ["4", "14"]
            ];

Позвольте мне объяснить первый вывод: ["1.1", "p,q"]:

Это первый лист. Это путь: "1" -> "1.1". Значения в пути: "p", "q".


Позвольте мне объяснить второй вывод: ["1.2.1", "p,a,b,c,d"]:

Это второй лист. Здесь я рассматривал повторяющиеся ключи как расширение одного. ["1.2", "a"],["1.2", "b"],["1.2", "c"] означает ["1.2", "abc"] .

Итак, путь второго листа: «1» -> («1.2» + «1.2» + «1.2») -> «1.2.1».


Позвольте мне объяснить пятый вывод:["1.4x", "7"] :

Обратите внимание: это не "p,7". Поскольку у ключа есть хвост «x», этот лист не должен принимать «p» в выходных данных.

Та же логика применима и для седьмого выхода.


Что я сделал до сих пор:

Вот мои попытки решить этот вопрос на данный момент.

Это фрагмент кода, который я использую прямо сейчас:

//////////////////////////////////////

function getTreeBranch(arr, c, p) {

    var outputArr = [],
    s = [],
    curr,
    next;

    for (var i = 0; i < arr.length - 1; i++) {
        curr = arr[i];
        next = arr[i + 1];
        currLevel = curr[c].split(".").length
        nextLevel = next[c].split(".").length

            if (currLevel == 1) {
                s = []
                s.push(curr[p]);
                if (currLevel == nextLevel)
                    outputArr.push([curr[c], s.join(',')]);
            } else if (currLevel < nextLevel) {
                s.push(curr[p]);
            } else if (currLevel == nextLevel) {
                s.push(curr[p]);
                outputArr.push([curr[c], s.join(',')]);
                s.pop();
            } else if (currLevel > nextLevel) {
                outputArr.push([curr[c], s.join(',') + ',' +curr[p]]);
                for (j = 0; j < (currLevel - nextLevel); j++) {
                    s.pop()
                }
            }
    }

    var lastItem = arr[arr.length - 1];
    if ((lastItem[c].length) == 1) {
        s = []
    }
    s.push(lastItem[p]);
    outputArr.push([lastItem[c], s.join(',')]);

    return outputArr

}

Но эта функция не может обрабатывать повторяющиеся ключи и завершающие 'x'.


Можете ли вы предложить какое-либо исправление или обновление, какой-либо альтернативный фрагмент кода, какой-либо алгоритм или намек на проблему? Любая помощь будет высоко ценится.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
115
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Предотвратить разделение суффикса values with 'x'`.

const
    getPathes = ({ value = [], sub }) => sub
        ? Object
            .entries(sub)
            .flatMap(([k, v]) => getPathes(v).map(([p, s]) => [
                k + (p && '.') + p, 
                [...value, ...s]
            ]))
        : [['', value]],
    input = [["1", "p"], ["1.1", "q"], ["1.2", "a"], ["1.2", "b"], ["1.2", "c"], ["1.2.1", "d"], ["1.2.2", "4"], ["1.2.2.1", "5"], ["1.3", "6"], ["1.4x", "7"], ["2", "8"], ["2.1", "9"], ["2.2", "10"], ["2.2.1x", "11"], ["2.2.2", "12"], ["3", "13"], ["4", "14"]],
    tree = input.reduce((t, [path, value]) => {
        const
            keys = path.endsWith('x')
                ? [path]
                : path.split('.'),
            target = keys.reduce((o, k) => (o.sub ??= {})[k] ??= {}, t);
        (target.value ??= []).push(value);
        return t;
    }, {}),
    result = getPathes(tree);

result.forEach(([k, v]) => console.info(k, ...v));
console.info(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

вы действительно должны использовать тот же стиль, что и ОП. шорткод (? :) в любом случае менее читаем.

WeAreDoomed 02.02.2023 16:07
Ответ принят как подходящий

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

Затем, предполагая, что inputArr находится в правильном порядке, найдите всех родителей и включите их (опять же, с особым случаем, когда есть «x»).

const inputArr = [["1","p"],["1.1","q"],["1.2","a"],["1.2","b"],["1.2","c"],["1.2.1","d"],["1.2.2","4"],["1.2.2.1","5"],["1.3","6"],["1.4x", "7"],["1.4x", "s"],["1.4x", "g"],["2","8"],["2.1","9"],["2.2","10"],["2.2.1x","11"],["2.2.2","12"],["3","13"],["4","14"]]

const outputArr = [...new Set(inputArr.map(([k])=>k))]
  .map(k=>[k,inputArr.filter(([i])=>i===k).map(([k,v])=>v)]).filter(([a])=>
    a.endsWith('x') || !inputArr.some(([b])=>b!==a && b.startsWith(a)
)).map((([a,b])=>[a,(a.endsWith('x')?b:
  inputArr.filter(([c])=>a.startsWith(c)).map(([c,d])=>d)).join(',')
]))

console.info(outputArr)

Я поражен тем, как вы решили это. Если я хочу удалить хвост «x» в выходном массиве? Таким образом, пятый элемент в выводе будет: ["1.4", "7"] вместо ["1.4x", "7"].

Imran Al Rashid 02.02.2023 16:45

@ImranAlRashid, ты можешь outputArr.map(([k,v])=>[k.replace('x',''),v]). Или сделайте это как часть моего кода выше, заменив .map((([a,b])=>[a, на .map((([a,b])=>[a.replace('x',''),

Andrew Parks 02.02.2023 17:03

Спасибо! Мне нравится ваш код, потому что он точен. Но у него все еще есть одна проблема, которую нужно решить. Если во входном массиве есть ["1.4x", "7"],["1.4x", "s"],["1.4x", "g"], выходной массив должен быть: ["1.4x", ["7","s","g"]]

Imran Al Rashid 02.02.2023 18:21
["1.4x", "7"],["1.4x", "s"],["1.4", "g"] должен выдать результат ["1.4", "7,s,g"]. «1,4x», «1,4x», «1,4» следует рассматривать как единое целое.
Imran Al Rashid 02.02.2023 20:10

этот вопрос может вас заинтересовать: stackoverflow.com/questions/75461049/…

Imran Al Rashid 15.02.2023 15:15

Большое спасибо за вашу помощь. Чтобы разместить 3 элемента в подмассивах, я изменил .map((([a,b]) на .map((([a,b,c]) И после .join(',') добавил: , inputArr.filter(([c])=>a.startsWith(c)).map(([c,d,e])=>e)).j‌​oin(',') Можете ли вы предложить более короткое выражение? пример: inputArr=[["1","p","p1"],["1.1","q","q1"]]outputArr=[["1.1","p,q","p1,q1"]]

Imran Al Rashid 16.02.2023 13:53

Вот общий процесс сокращения разделов:

  1. Вам нужно будет сначала отфильтровать разделы, оставив те, которые:
    • заканчиваться на "x" или
    • начинается с другого раздела
  2. Теперь вы можете сопоставить отфильтрованный раздел с парой ключ-значение.
    • Ключ:
      • Замените любой завершающий «x» на ключ
    • Ценить:
      • Если идентификатор ссылки заканчивается на «x», используйте значение для этого раздела.
      • В противном случае отфильтруйте разделы по их идентификатору, который предшествует идентификатору ссылки.
      • Соедините значения запятой

Полный пример

const inputArr = [
  ["1", "p"], ["1.1", "q"], ["1.2", "a"], ["1.2", "b"], ["1.2", "c"], ["1.2.1", "d"],
  ["1.2.2", "4"], ["1.2.2.1", "5"], ["1.3", "6"], ["1.4x", "7"], ["2", "8"],
  ["2.1", "9"], ["2.2", "10"], ["2.2.1x", "11"], ["2.2.2", "12"], ["3", "13"],
  ["4", "14"]
];

const rollupSections = (sections, specialSuffix = '', stripSuffix = false) =>
  sections
    .filter(([id]) =>
      id.endsWith(specialSuffix) ||
      !sections.some(([subId]) => subId !== id && subId.startsWith(id)))
    .map((([id, value]) => [
      // Key
      specialSuffix && stripSuffix
       ? id.replace(new RegExp(`${specialSuffix}$`), '')
       : id,
      // Value
      id.endsWith(specialSuffix)
        ? [value].join(',')
        : sections
          .filter(([subId]) => id.startsWith(subId))
          .map(([, subValue]) => subValue)
          .join(',')
    ]));

const outputArr = rollupSections(inputArr, 'x', true);

outputArr.forEach(pair => console.info(JSON.stringify(pair)));
.as-console-wrapper { top: 0; max-height: 100% !important; }

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

const inputArr = [
  ["1", "p"], ["1.1", "q"], ["1.2", "a"], ["1.2", "b"], ["1.2", "c"], ["1.2.1", "d"],
  ["1.2.2", "4"], ["1.2.2.1", "5"], ["1.3", "6"], ["1.4x", "7"], ["2", "8"],
  ["2.1", "9"], ["2.2", "10"], ["2.2.1x", "11"], ["2.2.2", "12"], ["3", "13"],
  ["4", "14"]
];

const endsWithSpecialSuffix = ([id], specialSuffix) =>
  id.endsWith(specialSuffix);

const isChildOf = (id, parentId) => id.startsWith(parentId);

const hasParentSection = ([id], sections) =>
  sections.some(([subId]) => subId !== id && isChildOf(subId, id));

const isChildSection = (section, sections, specialSuffix) =>
  endsWithSpecialSuffix(section, specialSuffix) ||
  !hasParentSection(section, sections)

const childSections = (sections, specialSuffix) =>
  sections.filter((section) => isChildSection(section, sections, specialSuffix));

const formatKey = ([id], specialSuffix, stripSuffix) =>
  specialSuffix && stripSuffix
     ? id.replace(new RegExp(`${specialSuffix}$`), '')
     : id;

const hasSuffix = (id, specialSuffix) => id.endsWith(specialSuffix);

const formatSubValues = (id, sections) =>
  sections
    .filter(([subId]) => id.startsWith(subId))
    .map(([, subValue]) => subValue)
    .join(',');

const formatValue = ([id, value], sections, specialSuffix) =>
  hasSuffix(id, specialSuffix)
    ? [value].join(',')
    : formatSubValues(id, sections)

const rollupSections = (sections, specialSuffix = '', stripSuffix = false) =>
  childSections(sections, specialSuffix).map(((section) => [
    formatKey(section, specialSuffix, stripSuffix),
    formatValue(section, sections, specialSuffix)
  ]))

const outputArr = rollupSections(inputArr, 'x', true);

outputArr.forEach(pair => console.info(JSON.stringify(pair)));
.as-console-wrapper { top: 0; max-height: 100% !important; }

Другие вопросы по теме