0

The facts:

  • I have several arrays (anywhere from 2 to dozens), all comprised of CSS classes.
  • Every class in each array is namespaced with one of the following: 'alignment__', 'font__', 'leading__', 'size__', or 'tracking__'.
  • The values in the arrays will not usually be in the same order.
  • The arrays will not always contain a value for each namespaced class.

What I need:

  • If the value for each namespace is the same in every array, I need to return the className without the namespace.
  • If the value for any namespace is different in any array, I need to return false.

Example:

Here is a small example of a collection of arrays I’ll be working with:

p1 = ["alignment__left", "size__18px", "leading__170", "tracking__0", "font__Operator--1408"];
p2 = ["size__18px", "tracking__0", "font__Operator--1408", "alignment__left"];
p3 = ["alignment__left", "size__18px", "leading__170", "tracking__0", "font__Operator--1408"];
p4 = ["alignment__left", "size__18px"];

This collection of arrays should return something like:

return {
    alignment: 'left',
    font: false,
    leading: false,
    size: '18px',
    tracking: false
}

Suggestions? Every angle I approach this from just seems slow and inefficient. I’m using lodash in this project, in case that simplifies things at all.

2
  • If you downvote the question, please leave a comment explaining why. Commented Feb 13, 2016 at 19:45
  • Maybe post the code you've already attempted into your question. Commented Feb 13, 2016 at 19:48

4 Answers 4

1

Here's something I threw together.

'use strict';
const originalArrays = [
  ["alignment__left", "size__18px", "leading__170", "tracking__0", "font__Operator--1408"],
  ["size__18px", "tracking__0", "font__Operator--1408", "alignment__left"],
  ["alignment__left", "size__18px", "leading__170", "tracking__0", "font__Operator--1408"],
  ["alignment__left", "size__18px"]
]
const countInArray = (array, what) => {
  lt count = 0;
  for(let i = 0; i < array.length; i++) {
    if(array[i] === what) {
      count++;
    }
  }
  return count;
};
const theFunction = (originalArrays) => {
  const flattenedArray = originalArrays.reduce((a, b) => a.concat(b));
  let interimResults = [];
  let results = {};

  for(let item of flattenedArray) {
    if(countInArray(flattenedArray, item) === originalArrays.length) {
      if(interimResults.indexOf(item) === -1) {
        interimResults.push(item)
      }
    } else {
      results[item.split('__')[0]] = false;
    }
  }

  for(let result of interimResults) {
    let parts = result.split('__');
    results[parts[0]] = parts[1];
  }
  return results;
};
Sign up to request clarification or add additional context in comments.

Comments

1

Find below a simple way to achieve that using lodash:

const u = require('lodash');

var p1 = ["alignment__left", "size__18px", "leading__170", "tracking__0", "font__Operator--1408"];
var p2 = ["size__18px", "tracking__0", "font__Operator--1408", "alignment__left"];
var p3 = ["alignment__left", "size__18px", "leading__170", "tracking__0", "font__Operator--1408"];
var p4 = ["alignment__left", "size__18px"];

// I will obtain the unique values from the arrays given using the `union` method:
var union = u.union(p1, p2, p3, p4)

// Then, I will create an array of unique values that are included in all given arrays.
var inter = u.intersection(p1, p2, p3, p4)

// Finally, you can use the `difference` method to obtain those unique values 
// that are not included in the `union` array.
var diff = u.difference(union, inter);

So, in the inter array you will have the classNames that have the same value in all of the array defined above (p1, p2, p3, p4) and the diff array will have all of the namespaces that were not included in each array.

Comments

0

I haven't tested this. If I understand your problem correctly the following could be one of the ways to solve this. I cannot say if this is optimal. I'll try to figure out a better way. But for now here's the code.

var functionWhichHasAccessToArrays() {
    var totalNoOfArrays = someNumber; // 2 or dozens

    function doAllArraysHaveSameValue(value) {
        return !!(_.every(arrayOfArrays, function(array) {
            return (-1 !== _.indexOf(array, value));
        }));
    }

    var result = {};
    _.each(arrayWithMaxLength, function(valueInArray){
        var keyValue = valueInArray.split('__');
        if (doAllArraysHaveSameValue(valueInArray)) {
           result[keyValue[0]] = keyValue[1];
        } else {
            result[keyValue[0]] = false;
        }
    })
}

Comments

0

Here's what I came up with. Didn't come out as clean as I intended but it seems to get the job done.

p1 = ["alignment__left", "size__18px", "leading__170", "tracking__0", "font__Operator--1408"];
p2 = ["size__18px", "tracking__0", "font__Operator--1408", "alignment__left"];
p3 = ["alignment__left", "size__18px", "leading__170", "tracking__0", "font__Operator--1408"];
p4 = ["alignment__left", "size__18px"];

var classes = [p1, p2, p3, p4],
    flat = classes.reduce(function(prev, curr) { return prev.concat(curr) }, []),
    unique = flat.reduce(function(prev, curr) { 
      return prev.indexOf(curr) == -1 ? prev.concat([curr]) : prev;
    }, []);

var result = {};

unique.forEach(function (style) {
  result[style.split('__')[0]] = classes.every(function (clss) {
    return clss.indexOf(style) !== -1;
  }) ? style.split('__')[1] : false;
})

document.getElementById('result').innerHTML = JSON.stringify(result, null, 4);
<body>
  <pre id="result">
  </pre>
</body>

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.