J'ai besoin de convertir un tableau de chemins:
const iterRow = (row, obj) => {
if (Array.isArray(row) && row.length !== 0) {
const [name, ...pathStack] = row;
const found = (n) => obj.children.find((i) => i.name === n);
if (obj.name === name) {
iterRow(pathStack, obj);
} else {
const newLeaf = {
name,
id: `${obj.id}.${name}`,
children: [],
};
if (!found(name)) {
obj.children.push(newLeaf);
}
iterRow(pathStack, found(name));
}
}
};
const argOptionsProcessed = (rows) => rows.reduce((acc, row) => {
const path = row.split('.');
const found = () => acc.find((item) => path[0] === item.name);
if (!found()) {
acc.push({ name: path[0], id: path[0], children: [] });
}
iterRow(path, found());
return acc;
}, []);
const paths = [
"test1",
"test1.test1children",
"test1.test1children.test1subchildren",
"test1.test1children.test1subchildren.test1subsubchildren",
"tets2",
"test2.test2children",
]
console.log(argOptionsProcessed(paths));en un objet avec la structure suivante:
{
name: "test1",
id: "test1",
children: [...test1 children],
}
J'essaye avec un réducteur et une fonction récursive par élément de tableau, cela fonctionne mais est assez lent. Toutes les suggestions pour améliorer ce code sont les bienvenues. Merci d'avance.
const paths = [ "test1", "test1.test1children" ]
3 Réponses :
Vous pouvez le faire sans récursivité en utilisant les méthodes forEach et reduction et un objet pour conserver les niveaux imbriqués.
const paths = [
"test1",
"test1.test1children",
"test1.test1children.test1subchildren",
"test1.test1children.test1subchildren.test1subsubchildren",
"test2",
"test2.test2children",
]
const result = []
const levels = { result }
paths.forEach(path => {
let id = '';
path.split('.').reduce((r, name, i, a) => {
id += (id ? '.' : '') + name;
if (!r[name]) {
r[name] = { result: [] }
r.result.push({ name, id, children: r[name].result })
}
return r[name]
}, levels)
})
console.log(result)
Vous avez raison! Merci beaucoup! Je vais essayer dans mon propre code merci encore
Vous pouvez adopter une approche plus courte en réduisant le tableau et le chemin et en recherchant le même nom.
.as-console-wrapper { max-height: 100% !important; top: 0; }
const
getTree = data => data.reduce((tree, path) => {
path.split('.').reduce((t, name, i, a) => {
let temp = t.find(q => q.name === name);
if (!temp) t.push(temp = { name, id: a.slice(0, i + 1).join('.'), children: [] });
return temp.children;
}, tree);
return tree;
}, []),
paths = ["test1", "test1.test1children", "test1.test1children.test1subchildren", "test1.test1children.test1subchildren.test1subsubchildren", "tets2", "test2.test2children"]
console.log(getTree(paths));
Voici une autre solution.
.as-console-wrapper { top: 0; max-height: 100% !important; }
const paths = [
"test1",
"test1.test1children",
"test1.test1children.test1subchildren",
"test1.test1children.test1subchildren.test1subsubchildren",
"test2",
"test2.test2children",
];
console.log(untangle(paths));
function untangle(paths) {
return paths.reduce( (a, v) => {
const path = v.split(".");
if (path.length < 2) {
const l0 = path[0];
let level0 = {name: l0, id: l0, children: []};
let tryChildren = paths
.filter( p => ~p.indexOf(".") && p.startsWith(l0) )
if (tryChildren.length) {
tryChildren = tryChildren.map( p => p.substr( p.indexOf(".")+1 ) );
level0.children = level0.children.concat(untangle(tryChildren));
}
a.push(level0);
}
return a;
}, []);
}
Cette question convient peut-être mieux à codereview.stackexchange.com
Btw je ne suis pas sûr si votre code fonctionne. Je récupère 3 objets au lieu de 2. L'objet avec l'id
test2est contenu deux fois.Et mieux vaut fournir une explication abstraite de l'algorithme que vous avez utilisé, afin que les gens puissent vous aider à améliorer cet algorithme et ne pas comprendre tout votre code.