2

I have an object of of arrays containing HTML classes:

var myObj = {
  classes1: ['.classI'],
  classes2: ['.classA', '.classB'],
  classes3: ['.class1', '.class2', '.class3'],
}

And I want to be able to join them into a string like so:

".classI.classA.class1, .classI.classA.class2, .classI.classA.class3, .classI.classB.class1, .classI.classB.class2, .classI.classB.class3"

Is there any way to iterate through each array in the object and combine the elements as above?

Thanks in advance.

4 Answers 4

4

Use nested loops.

var myObj = {
  classes1: ['.classI'],
  classes2: ['.classA', '.classB'],
  classes3: ['.class1', '.class2', '.class3'],
}

var result_array = [];
myObj.classes1.forEach(function(s1) {
  myObj.classes2.forEach(function(s2) {
    myObj.classes3.forEach(function(s3) {
      result_array.push(s1 + s2 + s3);
    });
  });
});
var result = result_array.join(', ');

console.log(result);

Sign up to request clarification or add additional context in comments.

2 Comments

Now what if the amount of arrays in the object is variable? Sometimes you might have 2 sometimes you might have 4@5c etc.? Could this be done recursively rather than with a fixed set of loops?
Yes, a recursive solution would be appropriate for an arbitrary number. The question wasn't specific, and showed no attempt to solve it on your own. If you want help with the recursive version, post your attempt.
1

It is a bit strange you start with an object with numbered properties like classesX with X being an incremental number. For such purposes an array is the more intuitive choice:

var myArr = [
    ['.classI'],
    ['.classA', '.classB'],
    ['.class1', '.class2', '.class3']
];

So I would suggest to start out with an array like that. Otherwise convert it first to one with this ES6 code:

var myArr = Object.keys(myObj).map(k => myObj[k]);

NB: With ES.Next (it is in ES2017 draft) you could write the above as:

var myArr = Object.values(myObj);

Then you could use this ES6 function to get the result you want, but in an array structure:

function cartesianConcat (a) {
    return a.reduce((b, c) => b.reduce((d, s) => d.concat(c.map( t => s + t )), []));
}

// sample data (in plain object form):
var myObj = {
  classes1: ['.classI'],
  classes2: ['.classA', '.classB'],
  classes3: ['.class1', '.class2', '.class3'],
};

// Object should really be an array:
var arr = Object.keys(myObj).map(k => myObj[k]);

// Get result and output as comma-separated string:
console.log(cartesianConcat(arr).join(', '));

The final join(', ') turns the result in the one string output you required.

Note that this solution keeps working if you have more (or less) levels in the input.

Comments

0

JS Fiddle

I realize there's already a pretty good answer. I was in the midst of doing my own before I realized, but in the interest of being complete this allows you to put in arrays in any order and is a function, meaning if you have to do this with a few different arrays this should allow you to do it with much less code.

It creates a function called pyramidArrange and when you pass it three arrays, it first sorts them for length and then performs the calculations returning a Set Objectof all the values. A Set Object you can think of as an array that only allows one of each value stored inside of it. It also gives you the easy ability to check what's within it by using SetObj.has(value)

var myObj = {
  classes2: ['.classI'],
  classes1: ['.classA', '.classB'],
  classes3: ['.class1', '.class2', '.class3'],
}

FirstArray = myObj.classes1;
SecondArray = myObj.classes2;
ThirdArray = myObj.classes3;

pyramidArrange(FirstArray, SecondArray, ThirdArray);

function pyramidArrange(firstArr, secondArr, thirdArr) {
  var ourSet = new Set();

  var ourArrays = [{
    array: firstArr,
    length: firstArr.length
  }, {
    array: secondArr,
    length: secondArr.length
  }, {
    array: thirdArr,
    length: thirdArr.length
  }];
  ourArrays.sort(function(a, b) {
    return a.length - b.length;
  });

  for (let val of ourArrays[0].array) {
    for (let val2 of ourArrays[1].array) {
      for (let val3 of ourArrays[2].array) {
        ourSet.add(val + val2 + val3);
      }
    }
  }
  return ourSet;
}

Comments

0

Here's my recursive solution to my question.

var concatFilters = function (obj){
    var data = [];

    var array = $.map(obj, function (value, index){
        return [value];
    });

    function iterate(lists){
        var values = [];

        function process(index){
            var list = lists[index];

            if(list){
                for(var i = 0; i < list.length; i++){

                    if(list[i]){
                        values[index] = list[i];
                    }
                    process(index + 1);
                }
            }

            var value = values.join('');

            if(data.indexOf(value) === -1){
                data.push(value);
            }

            return data;
        }

        for(var num = 0; num < lists.length; num++){
            process(num);
        }

        return data
    }

    iterate(array);

    var filters = data.filter(Boolean);

    return filters.join(', ');
};

var myObj = {
    classes1: ['.classI'],
    classes2: ['.classA', '.classB'],
    classes3: ['.class1', '.class2', '.class3'],
}

var concatVals = concatFilters(myObj);
console.log(concatValues);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.