1

I have simple CLI appliciation where user can specify category all individual object which will import to his project (similar as lodash custom builds)

To avoid duplicate data i create a object structure like:

{
    "front": {
        "subCategories": [{
            "name": "front1",
            "value": false
        }, {
            "name": "front2",
            "value": true
        }]
    },
    "other": {
        "subCategories": [{
            "name": "other1",
            "value": false
        }, {
            "name": "other2",
            "value": false
        }]
    }
}

and from user input i get

  • categorie/s name, e.g. string front (but it can list all categories as well)
  • or alternativly array of objects names, e.g. ['front1', 'other2']

Based on this input i have to figurate out if atleast one value is true. Just to note issue is not to know if user send category or individual objects, i know that from input parser :)

So i need to write 2 function which

  1. For each categories user pass to script (front, other in this example) check if atleast one value in any subcategories is true and if yea stop executing loop to avoid useless performance usage.
  2. Loop over all subcategorieis no mather parent and check if atleast single value is true where name is from array of object names from input e.g. ['front1', 'other2']

What i did try:

I can imagine that if I set objValue=false; as a default value and after that pass subCategories object to code similar as one below inside of loop may work:

var objValue = _.result(_.find(myObj, function(obj) {
    return obj.name === name;
}), 'value');

and before I call this i simply ask if(objValue) {//code here}

However this is something like final step, I am somehow lost at start.

If here someone who can lead me right way how to:

  • find if any value in object have value set to true
  • find in all subCategories(it can be a lot more then just 2) object if there is an object with value set to true
Andurit
  • 5,612
  • 14
  • 69
  • 121
  • 1
    Why won't you just make a forEach loop and return the values you need? For example you could iterate through your object and look for true values and return the name. If you need to go deeper you can use a simple recursion. – Megajin Aug 16 '16 at 09:56
  • Hi @Megajin thank you for your answer. I afraid i am not sure how to do what you explain. I consider my self as junior programmer. Is there a chance to provide some example code. It dont have to be an code for my specific object but something from which I will understand better. Thanks and I'm sorry for my lack of understanding – Andurit Aug 16 '16 at 10:01
  • I posted a function that performs a deep check for objects equality http://stackoverflow.com/questions/201183/how-to-determine-equality-for-two-javascript-objects/38661235#38661235 . You can easily modify it for your needs. – pmrotule Aug 16 '16 at 10:04
  • I will try to provide some code. Don't worry we all started at some point =). – Megajin Aug 16 '16 at 10:06
  • As I said I've provided you some code with explanations. Hope it helps to clear things up a bit. The answer provided by @Delosdos will work fine as well. – Megajin Aug 16 '16 at 10:58
  • @Megajin to be fair i marked Delosdos as corect answer because he answer first :) However your answer helped me as well. You've got thum up from me . Thanks a lot I appriciate it – Andurit Aug 16 '16 at 11:24

2 Answers2

1

Here you go, try this:

var data = {
    "front": {
        "subCategories": [{
            "name": "front1",
            "value": false
        }, {
            "name": "front2",
            "value": false
        }]
    },
    "other": {
        "subCategories": [{
            "name": "other1",
            "value": false
        }, {
            "name": "other2",
            "value": true
        }]
    }
}

function searchSubCategories(obj, subCats)
{
  var ret = false;
  for (var property in obj)
  {
      for (var i=0; i <obj[property].subCategories.length; i++){
        for (var x =0; x < subCats.length; x++)
        {
          ret = (obj[property].subCategories[i].name === subCats[x] && obj[property].subCategories[i].value === true);
          if (ret)
            break;
        }
        if (ret)
            break;
      }
    if (ret)
      break;
  }
  return ret;
 }

function searchCategory(obj, category){
  var ret = false;
  for (var i=0; i <obj[category].subCategories.length; i++)
  {
    ret = obj[category].subCategories[i].value;
    if (ret)
      break;
  }
  return ret;
}

console.log(searchSubCategories(data, ['front1', 'other2']));
console.log(searchCategory(data, 'other'));
console.log(searchCategory(data, 'front'));
Andy-Delosdos
  • 3,560
  • 1
  • 12
  • 25
  • Hi @Delosdos, thank you for your answer. I have to say that second part with looping over single property of data object works perfectly as expected. First part which loop over whole object doesnt consider user input. So in other words in my specific example: if user say he want specific object front1 and other1 both values is false but loop will return true because front2 is true – Andurit Aug 16 '16 at 10:14
  • Did you want it to only return true if ALL subcategories have a value of true? – Andy-Delosdos Aug 16 '16 at 10:15
  • Nope, i am sorry if my words misslead you. My english is not fluent so it may sounds like that. I wanted based on user input check object which user specific if atleast one of their value = true – Andurit Aug 16 '16 at 10:20
  • OK i think i see what you mean. You want function 2 to check an array of properties ['front1', 'other2'] for example. Should it return just one bool `{ false}`, or two bools? `{false, false}`? – Andy-Delosdos Aug 16 '16 at 10:34
  • Yea @Delosdos, i wanted just single result. So {false, false} = {false}, but if there is true somewhere like {false, true} = true i want true – Andurit Aug 16 '16 at 10:39
  • @Andurit - Have a look at my answer again, I have updated it. Does this help? – Andy-Delosdos Aug 16 '16 at 10:46
  • Thank you :) marked is correct answer and added thumb up :) Thanks again – Andurit Aug 16 '16 at 10:51
1
  • find if any value in object have value set to true
  • find in all subCategories(it can be a lot more then just 2) object if there is an object with value set to true

Following Steps should help you to understand how to start your desired action:

1. How many Categories are stored in the JSON?

      var myCategories = {
      "front": {
          "subCategorieA": [{
              "name": "front1",
              "value": false
          }, {
              "name": "front2",
              "value": true
          }],
          "subCategorieB": [{
              "name": "front1",
              "value": false
          }, {
              "name": "front2",
              "value": true
          }]
      },
      "other": {
          "subCategories": [{
              "name": "other1",
              "value": false
          }, {
              "name": "other2",
              "value": false
          }]
      } };

We've got front and other that makes 2. And some Subcategories.

For this example I've added subCategoriesB, because you mentioned there could be alot more.

2. Iterate through the find Categories

        //setup a for loop to get through the objects
        for(let key in myCategories){
        /**
        * do stuff
        */
        }

Please take note that under the current object structur, it is not possible to iterrate through your object like an array. For example you can not do:

myCategories[0]
// will throw error. An object is not an array!

3. Now that we can iterate through our objects all we need to do is pack all together and get the sub categories

We create a function which will return our desired Values:

// To keep it simple a for loop which looks for Keys in Object
// Example {key: value} => {front: subCategorieA, subCategorieB}
for(let key in myCategories){

  // Once we know the key, we can get the Value which is again an Object
  // In our case subCategorieA and subCategorieB for Key front
  getValuesFromSubcategories(myCategories[key]);
};

// This function simply returns the name of any value which is true
function getValuesFromSubcategories(mySubCategories){

  //to get Indexes for the arrays we have stored in our objects
  let counter = 0;

  // looks familiar right?
  for(let key in mySubCategories){

    if(mySubCategories[key][counter].value === true){

      //logs any Subcategorie name 
      console.log(mySubCategories[key][counter].name);
      /**
      * Do other needed stuff
      */
    }

    //increment correctly
    counter++;
  };
}

You saw my comment "looks familiar right"?. That is where you need to think about a recursion. But since you told me you are a junior programmer in Javascript I didn't want to confuse you any further. Just take note that you could pack all of this into one function which would call itself at some point to go to the deepest level of your object.

However the last part of code I've provided will log the name of any value which is true. You can customnize it from here on as you wish.

Hope this will make your question clear. If you have any further questions just comment =).

Regards, Megajin

Megajin
  • 2,648
  • 2
  • 25
  • 44