我有从DB查询的菜单列表,"示例"如下:
[
{ id: 1, name: 'Main Menu', branch: 1, subbranch1: 0, subbranch2: 0 },
{ id: 2, name: 'Main Menu 2', branch: 2, subbranch1: 0, subbranch2: 0 },
{ id: 3, name: 'Sub Menu 1-1', branch: 1, subbranch1: 1, subbranch2: 0 },
{ id: 4, name: 'Sub Menu 1-2', branch: 1, subbranch1: 2, subbranch2: 0 },
{ id: 5, name: 'Sub Menu 1-2-1', branch: 1, subbranch1: 2, subbranch2: 1 },
{ id: 6, name: 'Sub Menu 2-1', branch: 2, subbranch1: 1, subbranch2: 0 },
{ id: 7, name: 'Sub Menu 2-2', branch: 2, subbranch1: 2, subbranch2: 0 },
]
因此,每个菜单都有分支subbranch1 subbranch2值,表示它在菜单列表中的位置。这里的菜单可以是可点击的,或者只是用于分组菜单(拥有其子菜单)的组标题菜单。 例如,id为1的菜单中有3,4作为其子菜单1 另外,id为4的菜单中有5个作为子菜单。
我怎样才能找到所有没有孩子的菜单(或者只是一个可点击的菜单而不是组菜单)。
因此,给出样本的最终结果"应该像
[
{ id: 3, name: 'Sub Menu 1-1', branch: 1, subbranch1: 1, subbranch2: 0 },
{ id: 5, name: 'Sub Menu 1-2-1', branch: 1, subbranch1: 2, subbranch2: 1 },
{ id: 6, name: 'Sub Menu 2-1', branch: 2, subbranch1: 1, subbranch2: 0 },
{ id: 7, name: 'Sub Menu 2-2', branch: 2, subbranch1: 2, subbranch2: 0 },
]
答案 0 :(得分:3)
您可以先生成树,然后只选择最深的节点。
生成树
_
。获取最深的节点
_
,然后保留实际的迭代次数。_
,则找到最深的节点。对节点集合采取非常规的属性。离开迭代。返回结果。
function getDeepestNodes(nodes) {
function getDeepest(node) {
Object.keys(node).forEach(function (key) {
if (key === '_') {
return;
}
if (Object.keys(node[key]).length === 1 && '_' in node[key]) {
result.push(node[key]._);
return;
}
getDeepest(node[key]);
});
}
var levels = ['branch', 'subbranch1', 'subbranch2'],
tree = Object.create(null),
result = [];
nodes.forEach(function (node) {
var temp = tree;
levels.every(function (level, i, ll) {
temp[node[level]] = temp[node[level]] || {};
temp = temp[node[level]]
return node[ll[i + 1]];
});
temp._ = node;
});
getDeepest(tree);
return result;
}
var data = [{ id: 1, name: 'Main Menu', branch: 1, subbranch1: 0, subbranch2: 0 }, { id: 2, name: 'Main Menu 2', branch: 2, subbranch1: 0, subbranch2: 0 }, { id: 3, name: 'Sub Menu 1-1', branch: 1, subbranch1: 1, subbranch2: 0 }, { id: 4, name: 'Sub Menu 1-2', branch: 1, subbranch1: 2, subbranch2: 0 }, { id: 5, name: 'Sub Menu 1-2-1', branch: 1, subbranch1: 2, subbranch2: 1 }, { id: 6, name: 'Sub Menu 2-1', branch: 2, subbranch1: 1, subbranch2: 0 }, { id: 7, name: 'Sub Menu 2-2', branch: 2, subbranch1: 2, subbranch2: 0 }],
result = getDeepestNodes(data);
console.log(result);

.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 1 :(得分:1)
这是非常复杂的嵌套循环测试结构。如果每一行都引用了它的直接父菜单的id,那么迭代和测试将是微不足道的。假设这是您描述的菜单结构:
+-------------+
| Main Menu |
+-------------+
+--------------+
| Sub Menu 1-1 |
+--------------+
| Sub Menu 1-2 |
+--------------+
+----------------+
| Sub Menu 1-2-1 |
+----------------+
+-------------+
| Main Menu 2 |
+-------------+
+--------------+
| Sub Menu 2-1 |
+--------------+
| Sub Menu 2-2 |
+--------------+
要解决此问题,您需要执行以下操作:
old=<original array>
new= new array()
for (z=0;z<old.length;z++) // Loop through each line
{
linkonly = 1 // Using this prevents multiple
if (old[z].subbranch2 == 0) // If this is 3rd level, there is not sub menu
{
for (y=0;y<old.length;y++) // Loop through each line
{
if (z!=y ) // Don't check line against itself
{
if (old[z].branch == old[y].branch) // If both of these have the same main branch
{
if (old[z].subbranch1 != 0) // If this is a submenu, continue
{
if (old[z].subbranch1 == old[y].subbranch1) // They are in the same submenu section
{
if (old[y].subbranch2 != 0) // This is a submenu of the tested parent
{
linkonly = 0
y=old.length
}
}
}else{
if (old[y].subbranch1 != 0) // This is a submenu of the tested item
linkonly = 0
y=old.length
{
}
}
}
}
}
if (linkonly == 1)
{
// push line into new array
}
}
// use new array
更好的方法是将起始数据结构更改为:
[
{ id: 1, name: 'Main Menu', parent:0, pos:1 },
{ id: 2, name: 'Main Menu 2', parent:0, pos:2 },
{ id: 3, name: 'Sub Menu 1-1', parent:1, pos:1 },
{ id: 4, name: 'Sub Menu 1-2', parent:0, pos:2 },
{ id: 5, name: 'Sub Menu 1-2-1', parent:4, pos:1 },
{ id: 6, name: 'Sub Menu 2-1', parent:2, pos:1 },
{ id: 7, name: 'Sub Menu 2-2', parent:2, pos:2 },
]
然后你可以像这样测试它:
old=<original array>
new= new array()
for (z=0;z<old.length;z++) // Loop through each line
{
linkonly=1
for (y=0;y<old.length;y++) // Loop through each line
{
if (x!=y) // Don't test against itself
{
if (old[y].parent == old[x].id)
{
linkonly=0
y=old.length
}
}
}
if (linkonly == 1)
{
// push line into new array
}
}
// use new array
您还可以在多维数组中加载这些行,然后只需遍历它们,并通过检查子数组来确定是否存在子菜单。
答案 2 :(得分:0)
function isClickableMenu(menu, menus){
let noOfBranch;
let noOfSubbranch2;
if(menu.subbranch1 === 0){
noOfBranch = menus.reduce((acc,m)=>{
return m.branch === menu.branch ? acc + 1 : acc;
},0);
return noOfBranch === 1;
}
if(menu.subbranch2 === 0){
noOfSubbranch1 = menus.reduce((acc, m)=>{
return (m.subbranch1 === menu.subbranch1 && m.branch === menu.branch) ? acc + 1 : acc;
}, 0);
return noOfSubbranch1 === 1;
}
return true
}
function getClickableMenus(menus){
const newArray = [];
for (let i = 0; i < menus.length; i++) {
if(isClickableMenu(menus[i], menus)){
newArray.push(menus[i]);
}
}
return newArray;
}
const menus = [
{ id: 1, name: 'Main Menu', branch: 1, subbranch1: 0, subbranch2: 0 },
{ id: 2, name: 'Main Menu 2', branch: 2, subbranch1: 0, subbranch2: 0 },
{ id: 3, name: 'Sub Menu 1-1', branch: 1, subbranch1: 1, subbranch2: 0 },
{ id: 4, name: 'Sub Menu 1-2', branch: 1, subbranch1: 2, subbranch2: 0 },
{ id: 5, name: 'Sub Menu 1-2-1', branch: 1, subbranch1: 2, subbranch2: 1 },
{ id: 6, name: 'Sub Menu 2-1', branch: 2, subbranch1: 1, subbranch2: 0 },
{ id: 7, name: 'Sub Menu 2-2', branch: 2, subbranch1: 2, subbranch2: 0 },
];
console.log(getClickableMenus(menus));
&#13;
找到解决方案!..仍然可以有优化空间