-4

I've array of objects oDataSet and aProperties object and I want to match the identical values that are found in aPropertis and and In oDataSet and create the aSelectedDataSet which in beginning is an empty object

How it's recommend to do it in JS/Jquery

Note: there shouldnt be any hardcoded property in the loops/solution to do the match the aProperties is contain this value but it can be change (and of course there should be match in the oData object...)

For clarification Following is example how the objects is built

http://jsfiddle.net/4rh6tt25/5/

This is the input

 //This is given array of object which can be many ,here I put just two instance in the array for demonstration purpose
var oDataSet = [{
    __metadata: {
        aaa: 111,
        bbb: 222
    },
    to_ExcludedTerms: {results: []},
    to_ListTypeGroupAssignment: {
        results: [
            {
                AuthorisationGroup: 'AuthorisationGroup 1',
                ListTypeGroup: 'ListTypeGroup1',
                ListTypeGroupDescription: 'ListTypeGroupDescription 1',
                ParentKey: '8ae25d47-c3cc-4ee3-a040-ea00505692111',
                __metadata: {}
            },
            {
                AuthorisationGroup: 'AuthorisationGroup 2',
                ListTypeGroup: 'ListTypeGroup2',
                ListTypeGroupDescription: 'ListTypeGroupDescription 2',
                ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb7',
                __metadata: {}
            },
            {
                AuthorisationGroup: 'AuthorisationGroup 3',
                ListTypeGroup: 'ListTypeGroup3',
                ListTypeGroupDescription: 'ListTypeGroupDescription 3',
                ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb5',
                __metadata: {}
            }
        ]
    }
}, {
    //This is the second instance of the object with same keys but different values
    __metadata: {
        aaa: 333,
        bbb: 444
    },
    to_ExcludedTerms: {results: []},
    to_ListTypeGroupAssignment: {
        results: [
            {
                AuthorisationGroup: 'AuthorisationGroup 6',
                ListTypeGroup: 'ListTypeGroup6',
                ListTypeGroupDescription: 'ListTypeGroupDescription 6',
                ParentKey: '8ae25d47-c3cc-4ee3-a040-ea00505692116',
                __metadata: {}
            },
            {
                AuthorisationGroup: 'AuthorisationGroup 7',
                ListTypeGroup: 'ListTypeGroup7',
                ListTypeGroupDescription: 'ListTypeGroupDescription 7',
                ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb7',
                __metadata: {}
            },
            {
                AuthorisationGroup: 'AuthorisationGroup 8',
                ListTypeGroup: 'ListTypeGroup8',
                ListTypeGroupDescription: 'ListTypeGroupDescription 8',
                ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb8',
                __metadata: {}
            }
        ]
    }
}
];

//This is the values which I should search find in oDataSet
//The to_ListTypeGroupAssignment or other property which under the same structure
//should be with the following path but under the results which is the only
//hardcoded property
var aProperties = [
    "to_ListTypeGroupAssignment/ListTypeGroup",
    "to_ListTypeGroupAssignment/ListTypeGroupDescription"
]

This is the output

This is example of the output which should be build from the merge of both objects in the input above

var aSelectedDataSet = [
    {
        __metadata: {
            aaa: 111,
            bbb: 222
        },
        to_ListTypeGroupAssignment: {
            results: [
                {
                    ListTypeGroup: 'ListTypeGroup1',
                    ListTypeGroupDescription: 'ListTypeGroupDescription 1'
                },
                {
                    ListTypeGroup: 'ListTypeGroup2',
                    ListTypeGroupDescription: 'ListTypeGroupDescription 2',

                },
                {
                    ListTypeGroup: 'ListTypeGroup3',
                    ListTypeGroupDescription: 'ListTypeGroupDescription 3',
                }
            ]
        }
    },
    {
        __metadata: {
            aaa: 333,
            bbb: 444
        },
        to_ListTypeGroupAssignment: {
            results: [
                {
                    ListTypeGroup: 'ListTypeGroup1',
                    ListTypeGroupDescription: 'ListTypeGroupDescription 1'
                },
                {
                    ListTypeGroup: 'ListTypeGroup2',
                    ListTypeGroupDescription: 'ListTypeGroupDescription 2',

                },
                {
                    ListTypeGroup: 'ListTypeGroup3',
                    ListTypeGroupDescription: 'ListTypeGroupDescription 3',
                }
            ]
        }
    }

]

just to clarify from the comments below :) The only thing that can be hard-coded is the results. Not any property name like ListTypeGroup& ListTypeGroupDescription This should be generic and read from aProperties

The structure of you look at the oData should be like following

property(like -> to_ListTypeGroupAssignmen)
        results(hardcoded & mandatory in every exist object)
             properties(like ListTypeGroup& ListTypeGroupDescription with there values)

If I need to make it more clear please let me know How,which additional info I should add...This is after I update the question as much as possible...

07_05_GuyT
  • 2,787
  • 14
  • 43
  • 88
  • 5
    Can you please replace the image with code? It is much easier for people to try and reconstruct your issue copying and pasting code, rather than reading it from an image. See [How to Ask](http://stackoverflow.com/help/how-to-ask). – Tushar Mar 17 '16 at 14:02
  • Map it: `oPushedObject = oData.map(function(o) { return { ListTypeGroup: o.ListTypeGroup, ListTypeGroupDescription: o.ListTypeGroupDescription }; });` ??? – A. Wolff Mar 17 '16 at 14:18
  • @A.Wolff - Im tring it now and let yo know in 2 min :) – 07_05_GuyT Mar 17 '16 at 14:21
  • @A.Wolff - Its a bit more complicated :( I dont want to use the key hardcoded as you put (listTypeGroup & listTypeGroupDescription) .... – 07_05_GuyT Mar 17 '16 at 14:23
  • So what is your expected behaviour??? If not hardcoded, how do you target specific object keys? – A. Wolff Mar 17 '16 at 14:27
  • @A.Wolff - if there is match between those values in the both object (here is ---> listTypeGroup & listTypeGroupDescription) but it can be any values that exist in both object and then add it to oPushedObject... – 07_05_GuyT Mar 17 '16 at 14:30
  • Related (perhaps): http://stackoverflow.com/q/7364150/215552 – Heretic Monkey Mar 17 '16 at 14:32
  • @MikeMcCaughan - can you please provide example with my context – 07_05_GuyT Mar 17 '16 at 14:33
  • 4
    Part of learning to program is to program stuff yourself. How about you try to apply that related question to your own code, then ask a specific question regarding where you're having an issue? – Heretic Monkey Mar 17 '16 at 14:36
  • Then do nested loops to check for relevant properties. But your initial question was really unclear and you don't show many effort, do you??? That's said, see if that fits your needs: https://jsfiddle.net/m6zg8gcw/ – A. Wolff Mar 17 '16 at 14:42
  • @A.Wolff - I update the fiddle with my exact needed please have a look and see if you can help ,Thanks https://jsfiddle.net/m6zg8gcw/12/ – 07_05_GuyT Mar 17 '16 at 15:19
  • @A.Wolff - I need the undifend values in the oPushedObject to be filled ....but not hard coded :) – 07_05_GuyT Mar 17 '16 at 15:21
  • 1
    @A.Wolff - sorry this is the right https://jsfiddle.net/m6zg8gcw/13/ – 07_05_GuyT Mar 17 '16 at 15:23
  • http://underscorejs.org/ Is a good library for this kind of task. You can use _.findWhere or _.isMatch to find properties of objects to compare them – Thomas Illingworth Mar 17 '16 at 15:39
  • @ThomasIllingworth - Thanks but I cannot use undersocre and lodash in our project :( – 07_05_GuyT Mar 17 '16 at 15:40
  • 1
    @A.Wolff - is it a problem ?what do you think ? thank you! – 07_05_GuyT Mar 17 '16 at 16:01
  • What's a hardcoded property? – Stefano Nardo Mar 20 '16 at 17:07
  • 1
    Please re-read the official [how to ask a good question](/help/how-to-ask) article, and adjust your post accordingly. You're not describing your problem all that well, your code is not minimal, and you haven't shown what you've tried so far, why you think that should work, what you see it do instead, and why you can't figure out why that is wrong. – Mike 'Pomax' Kamermans Mar 20 '16 at 17:11
  • The only problem I see is that your search values don't follow the object path exactly as you have it in the object you need to search. Wouldn't `"to_ListTypeGroupAssignment/results/ListTypeGroup"` make a little more sense, otherwise you have to hardcode the check for a property name "results" – MiltoxBeyond Mar 20 '16 at 17:18
  • 1
    @StefanoNardo - hardcoded like listTypeGroup etc – 07_05_GuyT Mar 20 '16 at 17:24
  • 2
    @MiltoxBeyond - only results can be hardcoded :) forgat to mention this – 07_05_GuyT Mar 20 '16 at 17:26
  • @A.Wolff - please see my update question with fiddle and bounty ,Thanks :) – 07_05_GuyT Mar 20 '16 at 18:56
  • That much comments basically means that the question is poorly asked. We don't know how the output is supposed to look like and it's not clear how you want the "mapping" to behave. A bounty for an unspecific question can also be seen as a waste of time for posters since there is no "good answers" for that. Please improve your question by asking something specific, e.g. something that didn't work as expected in what you tried. If I understand correctly, you shown us the code for what you don't want to do. You should show us what you actually want to do. A bounty cannot improve a question. – Frederik.L Mar 20 '16 at 19:08
  • 4
    @Frederik.L - Thanks but I think you missed the point here...most of the comments was to the original question which I update today dramtically and create JsFiddle , The output should be aSelectedDataSet I put and example how it should be created(with the values),in addition at the bottom of the fiddle you can see what I try ,without success :( – 07_05_GuyT Mar 20 '16 at 19:27
  • 2
    I'm sorry but I must insist: you keep poorly asking what's your need, so even with good will nobody can really understand it. You seem to be always hurried, and it's not the good way to reach your goal. So please take the time to refactor your question _in a clear way_! Otherwise the time you're looking to save will be actually lost for you (because you'll not get any answer)... and for us! – cFreed Mar 20 '16 at 22:34
  • 1
    @cFreed OP also seems to have fake accounts or friends who constantly up-votes the question. It has many downvotes, yet it has a very positive score for such an unclear question. – Frederik.L Mar 21 '16 at 00:16
  • As suggested in meta, bounty protected questions that would need to be closed can be flagged. Otherwise it could be downvoted, which isn't a solution here since the OP always finds a way to get his score back up to positive. – Frederik.L Mar 21 '16 at 00:19
  • @Frederik.L - question with bounty cannot be deleted,why this question bother you ,if I need to improve please tell how ? if you are here to really help people? – 07_05_GuyT Mar 21 '16 at 05:33
  • 1
    @cFreed - can you tell me how it can be improved and i'll do that asap – 07_05_GuyT Mar 21 '16 at 05:34
  • @shopiaT It would be easier to understand your question if it was shorter and if it had only a specific part of the whole thing. The problem is, and of course I'm here to help people, is that people cannot figure out easily what could be the optimal answer to that question so they won't take the time to write one. Still trying to help, a good question should be a question for which the community would like to have an answer too. If this is a big picture with complex constraints, community won't benefit from the answer anyway and it's less tempting to put time into it. Keep it simple and clear. – Frederik.L Mar 21 '16 at 07:22
  • @shopiaT Bounty questions CAN be deleted, if it comes to the attention of a mod. They aren't mean at all, in fact they just fight really hard against natural tendencies we have to ask questions for ourselves. That's one thing that puts SO to another level IMO. – Frederik.L Mar 21 '16 at 07:29
  • @Frederik.L - please guide me how since at first the question was too short (two days ago) and I try to elaborate yesterday which is not so good also as you said ,Im stuck with it here can you help ? and pls remove your comment which is really screw my day :( – 07_05_GuyT Mar 21 '16 at 07:48
  • @Frederik.L - please be specific of what I can improve and I'll do it ASAP!Thanks – 07_05_GuyT Mar 21 '16 at 07:51
  • Why is your `aSelectedDataSet` returning 3 duplicate result sets? – Nick De Beer Mar 21 '16 at 14:49
  • @NickDeBeer - Hi Nick I've update the question is it more clear now ? – 07_05_GuyT Mar 21 '16 at 15:43
  • 1
    Yes thanks that makes sense, one more thing, should this only be for property to_ListTypeGroupAssignment or can you potentially have "__metadata/aaa" or "to_ExcludedTerms/some value" included in the result? In other words can the above values ever exist in `aProperties`? – Nick De Beer Mar 21 '16 at 15:49
  • @NickDeBeer - not necessarily – 07_05_GuyT Mar 21 '16 at 16:03
  • Really wish we could vote to close questions with an open bounty. This question is unclear. – bhspencer Mar 21 '16 at 16:42
  • From the example you have given its clear you want to merge two set of data with one of them missing some properties. Please confirm if this is the case ? – Thanigainathan Mar 21 '16 at 16:49
  • @Thanigainathan- the aSelectedDataSet is empty and should be created after the "merge" between the objects in the input – 07_05_GuyT Mar 21 '16 at 17:12
  • 1
    I don't get it. Which objects from the input are "merged"? All I can see is a bit of trivial filtering of properties. – Bergi Mar 21 '16 at 17:18
  • 1
    Why do you want `__metadata` to be in the result, when it is not specified in `aProperties`? – trincot Mar 21 '16 at 17:49
  • @Bergi - The object values inside aProperties should be merged into the new object aSelectedDataSet,is it more clear now? – 07_05_GuyT Mar 21 '16 at 18:22
  • @trincot - yes I know the 'results' and '__metadata' should be there for any type of properties (the sturcture of them is hard-coded but only for them...)\ – 07_05_GuyT Mar 21 '16 at 18:24
  • 2
    Why do you ***not*** include the `__metadata` of the inner objects then!? Is that another unspecified exception to an unspecified exception? You really need to get your question right. – trincot Mar 21 '16 at 19:11
  • So you are using aProperties as the schema and filter out other properties in the result except metadata and results. Am I right ? – Thanigainathan Mar 21 '16 at 20:24

5 Answers5

4

You could use this recursive, pure JavaScript function:

The snippet below applies this function to the example data you provided and returns the required result:

function extract(data, select, curpath) {
    var result = {};
    // Part of the path that has been traversed to get to data:
    curpath = curpath || '';        
    if (typeof data !== 'object') { // data is a primitive (we assume)
        return data;
    } 
    if (typeof data.slice === 'function') { // data is an Array
        return data.map(function (el, idx) {
            return extract(el, select, curpath); // same path!
        });
    }
    // data is an Object:
    // The specific case of the "__metadata" property
    if (data.__metadata !== undefined && curpath.length === 0) {
        result.__metadata = data.__metadata;
    }
    // Core of this algorithm: take the relevant paths only...
    var subselect = select.filter(function(path) {
        return (path+'/').indexOf(curpath) == 0;
    });
    subselect.forEach(function (path, _, subselect) {
        // then get the next property in such path...
        var prop = path.substr(curpath.length).split('/')[0];
        // and check if we have that property on the current object:
        if (data[prop] !== undefined) {
            // If so, recurse while adding this to the current path:
            result[prop] = extract(data[prop], subselect, curpath+prop+'/');
        }
    });
    // The specific case of the "results" property
    if (data.results !== undefined) {  // recurse with same path!
        result.results = extract(data.results, select, curpath);
    }
    return result;
} 


// Test data
var oDataSet = [{
    __metadata: {
        aaa: 111,
        bbb: 222
    },
    to_ExcludedTerms: {results: []},
    to_ListTypeGroupAssignment: {
        results: [
            {
                AuthorisationGroup: 'AuthorisationGroup 1',
                ListTypeGroup: 'ListTypeGroup1',
                ListTypeGroupDescription: 'ListTypeGroupDescription 1',
                ParentKey: '8ae25d47-c3cc-4ee3-a040-ea00505692111',
                __metadata: {}
            },
            {
                AuthorisationGroup: 'AuthorisationGroup 2',
                ListTypeGroup: 'ListTypeGroup2',
                ListTypeGroupDescription: 'ListTypeGroupDescription 2',
                ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb7',
                __metadata: {}
            },
            {
                AuthorisationGroup: 'AuthorisationGroup 3',
                ListTypeGroup: 'ListTypeGroup3',
                ListTypeGroupDescription: 'ListTypeGroupDescription 3',
                ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb5',
                __metadata: {}
            }
        ]
    }
}, {
    __metadata: {
        aaa: 333,
        bbb: 444
    },
    to_ExcludedTerms: {results: []},
    to_ListTypeGroupAssignment: {
        results: [
            {
                AuthorisationGroup: 'AuthorisationGroup 6',
                ListTypeGroup: 'ListTypeGroup6',
                ListTypeGroupDescription: 'ListTypeGroupDescription 6',
                ParentKey: '8ae25d47-c3cc-4ee3-a040-ea00505692116',
                __metadata: {}
            },
            {
                AuthorisationGroup: 'AuthorisationGroup 7',
                ListTypeGroup: 'ListTypeGroup7',
                ListTypeGroupDescription: 'ListTypeGroupDescription 7',
                ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb7',
                __metadata: {}
            },
            {
                AuthorisationGroup: 'AuthorisationGroup 8',
                ListTypeGroup: 'ListTypeGroup8',
                ListTypeGroupDescription: 'ListTypeGroupDescription 8',
                ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb8',
                __metadata: {}
            }
        ]
    }
}
];

var aProperties = [
    "to_ListTypeGroupAssignment/ListTypeGroup",
    "to_ListTypeGroupAssignment/ListTypeGroupDescription"
];
// (End of sample data)

// Call the function to get the result:
var aSelectedDataSet = extract(oDataSet, aProperties);

// For this snippet only: output the result in readable format
document.write('<pre>'+JSON.stringify(aSelectedDataSet, 0, 4)+'</pre>');

Explanation of the algorithm:

The code is commented. This is how the algorithm works:

  • The function is recursive and takes the current data, which will be just a sub section of the original data once the function is called recursively.
  • The function also takes the path-style properties to select. Also this list will be shorter as the function is called recursively, so it only has those entries that are still relevant to the data section.
  • The third argument is the path that has already been traversed. At the initial call this is just the empty string, but as the recursion kicks in, it will become 'to_ListTypeGroupAssignment/', and later even 'to_ListTypeGroupAssignment/ListTypeGroup/' (always with terminating slash).
  • Each call of the function will return a part of the given data that matches the (path-style) selection.
  • The function starts by identifying the type of the data: whether it is a primitive value (a string, number, boolean), or an array (which is the case at the initial call), or an (non-array) object.
  • If it is an array, the function is just called recursively for each element without adding anything to the path. The result of each call is then stored in an array, which becomes the return value.
  • If it is a primitive value, it means we recursed to a "leaf" in the "tree". And since we got here, we may assume the "path" was matching up until this point, and so the primitive value must be returned so it can be added to the result
  • It it is an object, the select paths are traversed to see if the next level in those paths matches with an object property of the current data. If so, that property value is passed via a recursive call, while also adding that piece of the path to the "current" path

There are obviously the exceptions for __metadata and results, which are treated separately in the code.

trincot
  • 317,000
  • 35
  • 244
  • 286
1

You will have to compare each property of oDataSet to each property of aSelectedDataSet

var res=[];
for (var key1 in oDataSet){
 for(var key2 in aSelectedDataSet ){
   if(key1==key2){
    res[key1]=oDataSet[key1];
   }
 }
}

EDIT:

If you define filter like so

var filter={
    __metadata:'',
    to_ListTypeGroupAssignment:{
        results:[{
            ListTypeGroup:'',
            ListTypeGroupDescription:''
        }]
    }

}

and apply it to data with recursion

function recursiveValue(filter,data){
    var res={};
    for(var key in filter){
        var val=data[key];
        var p=filter[key];
        if(val==='undefined') continue; 
        if(p===''){
            res[key] = val;
        }else if(Array.isArray(p)){
            var tmp = [];
            for(var i=0;i<val.length;i++){
                tmp.push(recursiveValue(filter[key][0],val[i]));
            }
            res[key] = tmp;
        }else if(typeof p=='object'){
            res[key] = recursiveValue(filter[key],val);
        }
    }
    return res;
}

like so

var results=[];
for(var i=0;i<oDataSet.length;i++){
    results.push(recursiveValue(filter,oDataSet[i]));
}

you get

console.log(results);
Martin
  • 1,752
  • 2
  • 13
  • 21
  • I try it but its not working,can you please use the jsFiddle which I provide? You dont refer to the results property, please use the code and I provide the exact output... – 07_05_GuyT Mar 21 '16 at 16:41
  • You code will not work(its not that simple...) since the aSelectedDataSet is just a var and its empty after the match it should be filled(like the output in the question...) – 07_05_GuyT Mar 21 '16 at 17:10
1

One of the short solutions will be with lodash. It has _.assignInWith(object, sources, [customizer]) function, using that you are going have the following:

var customizer = function(key) { return key in aPropertis }

var newSet = _.assignInWith({} , oDataSet, customizer)

However it is going to work only for first level properties.

vittore
  • 17,449
  • 6
  • 44
  • 82
1

You could tackle this using functional programming techiniques made available by ES5. Try this fiddle: https://jsfiddle.net/yh39of1b/3/

var aProperties = [
     "to_ListTypeGroupAssignment/ListTypeGroup",
     "to_ListTypeGroupAssignment/ListTypeGroupDescription"
];

//maps the properties you wish to capture
var propertyList = aProperties.map(function(properties) {
   return properties.split('/');
});

//reduces the oData array to the data you require
aSelectedDataSet = oData.reduce(function(existing,current){
     var obj = {};

     //each iteration of oData goes through each property group
     //first at the parent property level
     propertyList.forEach(function(property){
       if (typeof obj[property[0]] === 'undefined') {
        obj[property[0]] = {};
        obj[property[0]].results = [];
       }

       if(current[property[0]]) {
           //now at the child property level
           current[property[0]].results.forEach(function(result,index){
                 if(typeof obj[property[0]].results[index] === 'undefined')
                     obj[property[0]].results[index] = {};

                 obj[property[0]].results[index][property[1]] = result[property[1]];
           });
       }

   });
   //add the newly mapped object to the aSelectedDataSet array
   existing.push(obj);
   return existing;
},[]);
dewd
  • 4,380
  • 3
  • 29
  • 43
1

Not the most elegant way, but works.

JSFiddle Link

Compared nested structure and removed the keys which were not required.

Limitations:
1. __metadata is hardcoded
2. results is hardcoded

Your desired output is different then what is generated, difference is Your output:

aSelectedDataSet[2].to_ListTypeGroupAssignment.results[1].ListTypeGroupDescription === 1

Whereas in the generated output it is:

aSelectedDataSet[2].to_ListTypeGroupAssignment.results[1].ListTypeGroupDescription === 6

I think, it was a typo in your question.

Code:

var convertPropertyRelation = function(propertiesArray) {
  if (!Array.isArray(propertiesArray))
    return [];
  var formattedProperties = {},
    i, len = propertiesArray.length,
    currentRelation;
  for (i = 0; i < len; i++) {

    currentRelation = propertiesArray[i].split('/');

    if (formattedProperties.hasOwnProperty(currentRelation[0])) {
      formattedProperties[currentRelation[0]].push(currentRelation[1]);
    } else {
      formattedProperties[currentRelation[0]] = [currentRelation[1]];
    }

  }
  return formattedProperties;
};

var generateDataSet = function() {
  var formattedProperties = convertPropertyRelation(aProperties),
    firstRelation = Object.keys(formattedProperties),
    i, len = firstRelation.length,
    j, resultArray, resultLength;

  var dataSet = oDataSet.map(function(dataSetObject) {
    for (var firstKey in dataSetObject) {

      if (firstKey === '__metadata') {

        continue;

      } else if (firstRelation.indexOf(firstKey) === -1) {

        delete dataSetObject[firstKey];

      } else {

        // if first relation is present
        if (dataSetObject.hasOwnProperty(firstKey)) {
          // results array in the firstRelation
          resultArray = dataSetObject[firstKey].results;
          // for all results
          for (j = 0, resultLength = resultArray.length; j < resultLength; j++) {
            // for all keys in current result
            for (var respectiveKey in resultArray[j]) {
              // if the key is present leave it as it is
              if (formattedProperties[firstKey].indexOf(respectiveKey) === -1) {
                delete resultArray[j][respectiveKey];
              }
            }

          }

        }

      }

    }
    return dataSetObject;
  });

  return dataSet;
};
Bhavik
  • 4,836
  • 3
  • 30
  • 45