Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Filter" JSON for unique key and get all related values

What would be the best way to find all the possible related values with a group.

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"},
];

I want populate a Dropdown containing Unique group values. and on selection I want to use all related stuff for further processing. and also want to add a group which contains all stuff. for example

on selection of all -> new, old, newOld
                a -> new, old
                b -> newOld, old
                c -> new, old, newOld
like image 238
apaleja Avatar asked Jan 14 '23 01:01

apaleja


2 Answers

short and precise, without the overhead of looking up the entry each time in the whole array:

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

List the stuff in an object, thus you have no duplicate entries (that's why the rather redundant =1). But you could easily extend it to count the duplicates:

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

The result will look like the following:

// "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}
         }

To retrieve the values of a group, simply say:

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

Demo

Gotta watch out for support of Object.keys and Array.prototype.forEach of course.

like image 105
Christoph Avatar answered Jan 21 '23 03:01

Christoph


SOLUTION:

Using grep, map and unique (the usage of unique can be removed if "All" isn't needed). Here's the code :

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

SCENARIO :

We've got a dropdown with these options - a, b, c, All.

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

When an option is chosen, you'd like to get the relevant output from getOption() and display it as another 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");
});

DEMO http://jsfiddle.net/hungerpain/tSR5P/

EXTRA INFO ABOUT THE METHODS USED IN THIS SOLUTION

map

  1. Docs : http://api.jquery.com/jQuery.map/
  2. What it does : Translate all items in an array or object to new array of items. Kinda like a re-shaper of your json object.

unique

  1. Docs : http://api.jquery.com/jQuery.unique/
  2. What it does : Removes duplicates from an array.

grep

  1. Docs : http://api.jquery.com/jQuery.grep/
  2. Finds the elements of an array which satisfy a filter function.

Hope this helps!

like image 44
krishwader Avatar answered Jan 21 '23 03:01

krishwader