繁体   English   中英

计数数组中的(子)元素

[英]Counting (child) elements in arrays

我有一个对象数组。 每个对象看起来像这样:

{text: 'foo': level: N: children: M}

NM都是数字。 N表示对象的“深度”定位(考虑整个数组,就好像它是树的表示一样)。 M是该商品拥有的子代总数。 总计是指所有子级的所有节点和叶子的总和。

我拥有的数组中的对象不包含children属性,我必须对其进行计算。

“计算”数据的示例:

{text: 'A': level: 0: children: 0}
{text: 'B': level: 0: children: 1}
{text: 'C': level: 1: children: 0}
{text: 'D': level: 0: children: 2}
{text: 'E': level: 1: children: 1}
{text: 'F': level: 2: children: 0}

A
B
|--C
D
|--E
   |--F

我可以轻松地执行一个for循环,然后在数组的当前位置开始遍历项再迭代一次,并根据子级的属性对子级进行计数(但根据level属性),但是我觉得这并不是最好的方法(例如“最快”的方式。

我还能怎么做?

为了确保没有人发布比我当前拥有的“更糟糕”的代码,这就是我拥有的:

for (var i = 0; i < data.length; i++) {
    var item = data[i];

    for (var j = i + 1; j < data.length; j++) {
        if (item.level < data[j].level) {
            item.children++;
        } else {
            break;
        }
    }
}

在当前示例中,您根本无法计算孩子,因为您的数据没有显示父母/孩子的关系。 level:1表示text: 'C'例如, text: 'C'没有数据,如果应将其附加(即增加children计数器)到ABD

如果您的意思是,但忘了提及子对象应该附加到最近提到的任何最接近的父对象,则只需保留一个数组,其中每个条目将对应于对该级别最后一次看到的父元素的引用,并使用+=修改其chlildren属性+=读取每行后直接返回。

这就是我认为@Oleg V. Volkov在他的评论中建议的答案。 我认为这是一个非常好的解决问题的方法,而且非常快,因为您只看一次每个元素。 但是,不利的一面是,由于父级数组的存在,它在计算时可能会占用更多的内存。

function countChildren(tree) {
    var currentParents = [];

    for (var i = 0; i < tree.length; i++) {
        // Initialize value of children
        tree[i].children = 0;

        if (i == 0) {
            continue;
        }

        // Find if the level increased, decreased, or stayed the same.
        var levelChange = tree[i].level - tree[i-1].level;

        // If level increased (by 1)
        if (levelChange == 1) {
            // Add previous element to list of parents
            currentParents.push(tree[i-1]);

        // If level decreased by 'x'
        } else if (levelChange < 0) {
            // Remove 'x' number of elements from the end of the list of parents
            for (var j = 0; j > levelChange; j--) {
                currentParents.pop();
            }
        }

        // Increase the number of children for all parents
        for (var j = 0; j < currentParents.length; j++) {
            currentParents[j].children++;
        }
    }
}

从底部开始,这是一种不同的方法,请使用所有其他解决方案。

优点是,每当达到较小的电平时,都会求和,并将实际电平累加器设置为零。

该解决方案仅具有一个循环和一个用于级累加的数组count

我对此数据进行了更大的测试(属性children除外,这是算法的结果)。

 { text: 'A', level: 0, children: 0 }, // A { text: 'B', level: 0, children: 1 }, // B { text: 'C', level: 1, children: 0 }, // C { text: 'D', level: 0, children: 3 }, // D { text: 'E', level: 1, children: 2 }, // E { text: 'F', level: 2, children: 0 }, // F { text: 'F', level: 2, children: 0 }, // G { text: 'H', level: 0, children: 18 }, // H { text: 'I', level: 1, children: 5 }, // I { text: 'J', level: 2, children: 1 }, // J { text: 'K', level: 3, children: 0 }, // K { text: 'L', level: 2, children: 2 }, // L { text: 'M', level: 3, children: 1 }, // M { text: 'N', level: 4, children: 0 }, // N { text: 'O', level: 1, children: 10 }, // O { text: 'P', level: 2, children: 9 }, // P { text: 'Q', level: 3, children: 7 }, // Q { text: 'R', level: 4, children: 5 }, // R { text: 'S', level: 5, children: 2 }, // S { text: 'T', level: 6, children: 0 }, // T { text: 'U', level: 6, children: 0 }, // U { text: 'V', level: 5, children: 0 }, // V { text: 'W', level: 5, children: 0 }, // W { text: 'X', level: 4, children: 0 }, // X { text: 'Y', level: 3, children: 0 }, // Y { text: 'Z', level: 1, children: 0 }, // Z 

 var data = [{ text: 'A', level: 0 }, { text: 'B', level: 0 }, { text: 'C', level: 1 }, { text: 'D', level: 0 }, { text: 'E', level: 1 }, { text: 'F', level: 2 }, { text: 'F',level: 2 }, { text: 'H', level: 0 }, { text: 'I', level: 1 }, { text: 'J', level: 2 }, { text: 'K', level: 3 }, { text: 'L', level: 2 }, { text: 'M', level: 3 }, { text:'N', level: 4 }, { text: 'O', level: 1 }, { text: 'P', level: 2 }, { text: 'Q', level: 3 }, { text: 'R', level: 4 }, { text: 'S', level: 5 }, { text: 'T', level: 6 }, {text: 'U', level: 6 }, { text: 'V', level: 5 }, { text: 'W', level: 5 }, { text: 'X', level: 4 }, { text: 'Y', level: 3 }, { text: 'Z', level: 1 }], i = data.length, count = []; while (i--) { if (data[i].level > 0) { count[data[i].level - 1] = (count[data[i].level - 1] || 0) + (count[data[i].level] || 0) + 1; } data[i].children = count[data[i].level] || 0; count[data[i].level] = 0; } document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>'); 

带有预填充数组count (不检查未定义)和级别变量的版本。

 var data = [{ text: 'A', level: 0 }, { text: 'B', level: 0 }, { text: 'C', level: 1 }, { text: 'D', level: 0 }, { text: 'E', level: 1 }, { text: 'F', level: 2 }, { text: 'F',level: 2 }, { text: 'H', level: 0 }, { text: 'I', level: 1 }, { text: 'J', level: 2 }, { text: 'K', level: 3 }, { text: 'L', level: 2 }, { text: 'M', level: 3 }, { text:'N', level: 4 }, { text: 'O', level: 1 }, { text: 'P', level: 2 }, { text: 'Q', level: 3 }, { text: 'R', level: 4 }, { text: 'S', level: 5 }, { text: 'T', level: 6 }, {text: 'U', level: 6 }, { text: 'V', level: 5 }, { text: 'W', level: 5 }, { text: 'X', level: 4 }, { text: 'Y', level: 3 }, { text: 'Z', level: 1 }], i = data.length, l, count = Array.apply(null, { length: 50 }).map(function () { return 0; }); while (i--) { l = data[i].level; if (l) { count[l - 1] += count[l] + 1; } data[i].children = count[l]; count[l] = 0; } document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>'); 

我可以想到的唯一方法是不带for循环,这需要您改革树形结构。 JavaScript对象可以嵌套 ,因此我建议使用以下格式:

[
    {
        text: 'A',
        children: []
    },
    {
        text: 'B',
        children: 
        [
            {
                text: 'C',
                children: []
            }
        ]
     },
     {
         text: 'D',
         children:
         [
             {
                 text: 'E',
                 children:
                 [
                     {
                         text: 'F',
                         children: []
                     }
                 ]
             }
         ]
     }
]

然后,对于每个对象,“孩子总数”的公式将类似于:

function countChildren(obj) {
    var count = obj.children.length;
    for (int i = 0; i < children.length; i++) {
        count += countChildren(children[i]);
    }
    return count;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM