“过滤”JSON获取唯一键并获取所有相关值

时间:2013-06-25 13:18:02

标签: javascript jquery arrays json object

使用组查找所有可能相关值的最佳方法是什么。

var table = [
    {group:"a", stuff:"new"},
    {group:"a", stuff:"old"},
    {group:"b", stuff:"newOld"},
    {group:"b", stuff:"old"},
    {group:"c", stuff:"new"},
    {group:"c", stuff:"old"},
    {group:"c", stuff:"newOld"},
];

我想填充包含唯一group值的下拉列表。在选择时,我想使用所有相关的stuff进行进一步处理。并且还想添加一个包含所有stuff的组。例如

on selection of all -> new, old, newOld
                a -> new, old
                b -> newOld, old
                c -> new, old, newOld

6 个答案:

答案 0 :(得分:5)

简短而精确,没有每次在整个数组中查找条目的开销:

var groups = {all:{}};
table.forEach(function(a){
    if (!groups[a.group]){ groups[a.group] = {}; }
    groups[a.group][a.stuff] = groups["all"][a.stuff] = 1;
});

列出对象中的内容,因此您没有重复的条目(这就是相当多余的=1)。但你可以很容易地扩展它来计算重复数:

table.forEach(function(a){
    if (!groups[a.group]){ groups[a.group] = {}; }
    var stuff = groups["all"][a.stuff];
    groups["all"][a.stuff] = !stuff ? 1 : ++stuff;
    stuff = groups[a.group][a.stuff];
    groups[a.group][a.stuff] = !stuff ? 1 : ++stuff;
});

结果如下所示:

// "groups" holds all group elements and their stuff values
groups = { "all": {"new":2,"old":3,"newOld":2},
           "a" : {"new":1,"old":1},
           "b" : {"newOld":1,"old":1},
           "c" : {"new":1,"old":1,"newOld":1}
         }

要检索组的值,只需说:

var groupname = "a"; // whatever group you need
Object.keys(groups[groupname]);
// will give you:
["new","old"]

Demo

当然要小心Object.keysArray.prototype.forEach的支持。

答案 1 :(得分:3)

<强> SOLUTION:

使用grepmapunique(如果不需要“全部”,则可以删除unique的使用情况)。这是代码:

function getOptions(value) {
    //check if value sent in is an option or "All" options
    var isAll = value === "All" ? true : false;
    var forVal;
    //If its "All" options
    if (isAll) {
        //yes, "All" has been chosen. yay!

        //retreive all the values in "stuff" keys in array
        var internal = $.map(table, function (r) {
            return r["stuff"];
        })
        console.log(internal);
        //get the unique values in internal[]
        forVal = $.unique(internal);

        //or use grep instead if u like to use unique with only DOM elements

    } else {

        //use grep to filter out the other options except the chosen option
        var internal = $.grep(table, function (row) {
            return row["group"] === value;
        });

        //rip out the the values in "stuff" keys in internal[]
        forVal = $.map(internal, function (r) {
            return r["stuff"]
        });
    }
    //return the output variable
    return forVal;
}

情景

我们有一个包含这些选项的下拉菜单 - abcAll

<select id="questions">
    <option>All</option>
    <option>a</option>
    <option>b</option>
    <option>c</option>
</select>

选择option后,您希望获得getOption()的相关输出,并将其显示为另一个select

$("select").change(function () {
    //remove all #result select boxes - litter of previous option selection
    $("#result").remove();
    //get the options from the getOptions function
    var source = getOptions(this.value);
    //declare a select tag - will be inserted into <body> later
    var $select = $("<select/>", {
        "id": "result"
    });
    //construct an array of <option> tags
    var $options = $.map(source, function (r) {
        return $("<option/>", {
            "html": r
        });
    });
    //append $options to <Select> and then append $select to <body>
    $select.append($options).appendTo("body");
});

<强>样本 http://jsfiddle.net/hungerpain/tSR5P/

关于此解决方案中使用的方法的额外信息

<强> map

  1. 文档:http://api.jquery.com/jQuery.map/
  2. 它的作用:将数组或对象中的所有项目转换为新的项目数组。有点像你json对象的重塑。
  3. <强> unique

    1. 文档:http://api.jquery.com/jQuery.unique/
    2. 它的作用:从数组中删除重复项。
    3. <强> grep

      1. 文档:http://api.jquery.com/jQuery.grep/
      2. 查找满足过滤函数的数组元素。
      3. 希望这有帮助!

答案 2 :(得分:0)

你可能想要这样的东西:

var groups = {}, container = [], tracker = {};

for (var i = 0, l = table.length; i < l; i++)
{
    var group = table[i].group, stuff = table[i].stuff;

    if (!groups.hasOwnProperty(group)) groups[group] = [];
    groups[group].push(stuff);

    if (tracker.hasOwnProperty(stuff)) continue;
    container.push(stuff);
    tracker[group] = undefined;
}

其中groups包含组数据的对象,而容器包含所有唯一值。

答案 3 :(得分:0)

我认为这可行:

var table = [
    {group:"a", stuff:"new"},
    {group:"a", stuff:"old"},
    {group:"b", stuff:"newOld"},
    {group:"b", stuff:"old"},
    {group:"c", stuff:"new"},
    {group:"c", stuff:"old"},
    {group:"c", stuff:"newOld"}
];
var groups = {};
var all = [];

for(var i = 0; i < table.length; i++) {
    var group = table[i];    

    if(typeof groups[group.group] === "undefined") {
        groups[group.group] = [];
    }

    if (all.indexOf(group.stuff) == -1){
        all.push(group.stuff);
    }

    groups[group.group].push(
        group.stuff
    );       
}

all.sort();

因此变量all包含每个可能的值,而groups包含每个组的值:

console.log(groups.a)
> ["new", "old"]
console.log(groups.b)
> ["newOld", "old"]
console.log(groups.c)
> ["new", "old", "newOld"]

答案 4 :(得分:0)

查看示例here

var table = [
    {group:"a", stuff:"new"},
    {group:"a", stuff:"old"},
    {group:"b", stuff:"newOld"},
    {group:"b", stuff:"old"},
    {group:"c", stuff:"new"},
    {group:"c", stuff:"old"},
    {group:"c", stuff:"newOld"},
];

    var filter = function(selected) {    
        var newArr = [];
        $.each(table, function(idx, item){
            if((selected == null || selected == item.group) && $.inArray(item.stuff, newArr) == -1) {
                newArr.push(item.stuff);
            }
        });    
        return newArr;
    };

// using
    console.log(filter('a'));

// for selecting 'all'
    console.log(filter(null));

答案 5 :(得分:0)

很抱歉在这么长时间后提出这个问题,但我找不到解决方法。

我会采用一种更简单(但可能优化程度较低)的ES6方法:

我们从表格开始

const table = [
    { group: "a", stuff: "new" },
    { group: "a", stuff: "old" },
    { group: "b", stuff: "newOld" },
    { group: "b", stuff: "old" },
    { group: "c", stuff: "new" },
    { group: "c", stuff: "old" },
    { group: "c", stuff: "newOld" }
];

然后,我们希望所有唯一组值都作为数组,以便我们可以轻松地在选择元素中对其进行循环。

// Get all unique group entries in the table and map them to the value of group
const uniqueGroups = table.filter((entry, index, self) => {
    // findIndex will return the index of the first found result
    return self.findIndex(a => a.group === entry.group) === index;
).map(entry => entry.group);

为了争辩,想象有人点击了一个小组。

// Image someone clicked on the group "c"
const chosenGroup = uniqueGroups[2]; // This would be the event handler value of the chosen option

然后,我们过滤掉表中与该组值相对应的所有条目,并将实体映射到填充值。

// Get all stuff related to chosen group
const stuff = table.filter(entry => entry.group === chosenGroup).map(entry => entry.stuff);

我认为这样做更容易,对于少量数据完全没问题。