计算数组中的(子)元素

时间:2016-02-09 15:14:35

标签: javascript arrays

我有一个对象数组。每个对象如下所示:

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

NM都是数字。 N代表" deep"找到对象(想想整个数组就好像它是树的表示)。 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属性),但我觉得这样这不是最好的(如#34;最快")方式。

我还能怎么做?

只是为了确保没有人发帖"更糟糕"代码比我现在的代码,这就是我所拥有的:

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;
        }
    }
}

4 个答案:

答案 0 :(得分:2)

在您当前的示例中,根本无法计算子项,因为您的数据不显示父/子关系。例如,In [83]: df['DATE'] = pd.to_datetime(df['DATE']) df Out[83]: DATE TYPE VALUE 0 2016-01-31 yellow 10 1 2016-02-28 yellow 10 2 2016-02-28 red 20 3 2016-03-31 blue 20 4 2016-03-31 yellow 10 5 2016-02-28 blue 20 6 2016-02-28 red 10 7 2016-01-31 blue 10 8 2016-02-28 yellow 20 9 2016-01-31 blue 10 In [85]: df.groupby([df['DATE'].dt.month, df['TYPE']]).sum().reset_index() Out[85]: DATE TYPE VALUE 0 1 blue 20 1 1 yellow 10 2 2 blue 20 3 2 red 30 4 2 yellow 30 5 3 blue 20 6 3 yellow 10 的{​​{1}}没有数据,如果它应该附加(即增加level:1计数器)到text: 'C'children或{{1} }。

如果你的意思是,但是忘了提到那个子对象应该附加到最近提到的最近的父对象,那么只需保留一个数组,其中每个条目对应于对该级别的最后看到的父元素的引用并修改它{在阅读每一个新行后,{1}} {{}}}属性。{/ p>

答案 1 :(得分:1)

这是我认为@Oleg V. Volkov在评论中提出的答案。我认为这是解决问题的一个非常好的解决方案。非常快,因为你只看了1次每个元素。然而,不利的一面是,由于父母的数组,它在计算时可能会占用大量内存。

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++;
        }
    }
}

答案 2 :(得分:1)

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

优点是,只要达到较小的等级,就会得到总和,并将实际等级累加器设置为零。

此解决方案仅为级别累积提供了一个循环和一个数组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

&#13;
&#13;
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>');
&#13;
&#13;
&#13;

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

&#13;
&#13;
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>');
&#13;
&#13;
&#13;

答案 3 :(得分:0)

在没有for循环的情况下,我能想到的唯一方法就是要求你改革你的树形结构。 JavaScript对象可以嵌套,因此我建议使用以下格式:

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

然后对于每个对象,&#34;子女总数&#34;会是这样的:

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