【问题标题】:JavaScript: Indexing an object by column valuesJavaScript:按列值索引对象
【发布时间】:2012-03-15 19:15:07
【问题描述】:

我有一个如下所示的表格数组:

tablearray =
[
    {'column1': 1, 'column2': 1, 'column3': 1, 'column4': 2},
    {'column1': 1, 'column2': 2, 'column3': 3, 'column4': 4},
    {'column1': 2, 'column2': 0, 'column3': 4, 'column4': 6}
]

我正在尝试创建一个函数,该函数采用表数组和列名数组,并创建一个由列值索引的新对象。所以

newObject = indexByColumnValues(tablearray, ['column1', 'column2']);

应该产生类似的对象

newObject =
{
    1:
        {
            1: {'column1': 1, 'column2': 1, 'column3': 1, 'column4': 2},
            2: {'column1': 1, 'column2': 2, 'column3': 3, 'column4': 4}
        }
    2:
        {
            0: {'column1': 2, 'column2': 0, 'column3': 4, 'column4': 6}
        }
}

所以

newObject[1][1]['column3'] = 1
newObject[1][2]['column4'] = 4
etc...

如果列名数组(上面的['column1', 'column2'])中的列数是已知的,那么解决方法并不难。但是如果我允许这个数组中有任意数量的列名,它就会变得更加困难,因为存在无限递归

newObject[tablearray[columnNameArray[0]][tablearray[columnNameArray[1]][tablearray[columnNameArray[2]]...

这是一次尝试。我尝试使用指针指向 newObject 数组的维度深度。首先,指针 = newObject。然后指针 = newObject[...[0]]。然后点 = newObject[...[0]][...[1]]。等等。这会正确构建对象,但是我没有办法为 newObject[...[0]]...[...[k]] 赋值。

function indexByColumnValues(object, columnNameArray)
{
    var newObject = {};

    for(i in object)
    {
        var index=[];

        for(j in columnNameArray)
        {
            index.push(object[i][columnNameArray[j]]);
        }

        var pointer = newObject;

        for(j in index)
        {
            if(pointer[index[j]] == undefined)
            {
                pointer[index[j]] = {};
            }

            pointer = pointer[index[j]];
        }

        //now pointer points to newObject[index[0]][index[1]]...[index[k]]
        //but I need to set newObject[...] above to be object[i].  How?
        //pointer = object[i]; //won't work
    }

    return newObject;
}

任何帮助或提示在这里都会很棒。谢谢。

【问题讨论】:

  • 我不知道你是想使用库还是想从你自己的代码中学习(这很有帮助),但是 underscore.js 有 _.groupBy 可以满足你的需要之后。
  • 结果中的内部对象不应该是一个数组,其中包含每个对象与匹配的列一值吗?
  • @jfriend00 出于我的目的,由于我希望使用的列值组合是唯一的,因此内部数组将是不必要的。
  • @pimvdb 谢谢,我去看看。

标签: javascript arrays object multidimensional-array indexing


【解决方案1】:

您提到了递归,但您没有在代码中使用它。这是递归是正确工具的经典情况。这是一个实现:

function indexByColumnValues(table, cols) {
    // get the column we're indexing
    var col = cols[0],
        index = {},
        x, val;
    // find all values
    for (x=0; x<table.length; x++) {
        val = table[x][col];
        // add to index if necessary
        if (!index[val]) index[val] = [];
        // push this row
        index[val].push(table[x]);
    }
    // recurse if necessary
    if (cols.length > 1) {
        for (x in index) {
            if (index.hasOwnProperty(x)) {
                // pass the filtered table and the next column
                index[x] = indexByColumnValues(
                    index[x],
                    cols.slice(1)
                );
            }                
        }
    }
    return index;
}

请注意,正如@jfriend00 所指出的,您希望索引的“叶子”是一组匹配行,而不是单个对象 - 在您的示例中,您的给定数据只有一个匹配行,这只是巧合和一组列。用法:

indexByColumnValues(tablearray, ['column1','column2']);​

输出:

{
    "1":{
        "1":[
            {"column1":1,"column2":1,"column3":1,"column4":2}
        ],
        "2":[

            {"column1":1,"column2":2,"column3":3,"column4":4}
        ]
    },
    "2":{
        "0":[
            {"column1":2,"column2":0,"column3":4,"column4":6}
        ]
    }
}

JsFiddle:http://jsfiddle.net/RRcRM/3/

【讨论】:

  • 这很好用。谢谢你。我让它变得比需要的更难;使用递归函数肯定有帮助。
猜你喜欢
  • 2017-06-22
  • 1970-01-01
  • 1970-01-01
  • 2014-10-12
  • 1970-01-01
  • 2018-10-16
  • 2013-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多