3

I have some arrays, and if they contain similar values, I would like to return the name of those arrays.

    var x = {
      "food": ['bacon', 'cheese', 'bread', 'tomato'],
      "utilities": ['plates', 'forks', 'spatulas'],
      "guests": ['john', 'matt', 'bill']
    },
    y = ['bacon', 'tomato', 'forks'];

I have my variable x, and it has multiple arrays, with a name either food, or utilities, or guests. All that y contains, is some values that are the same within some of those arrays in the variable of x. I need to return the name of the arrays that contain bacon,tomato, and forks in their arrays. So for this example, I need to return: ["food", "utilities"].

    function getContainerName(obj, values) {
      return Object.keys(obj).find(function(key) {
        return values.every(value => obj[key].find(function(elem) {
          return elem === value;
        }));
      });
    }
    console.log(getContainerName(x, y));

When throwing them through this function, I get an error *********. How may I go and get a returned array of ["food", "utilities"]?

3 Answers 3

4

A simple reduce() on the Object.keys will do the job

var x = {
    "food": ['bacon', 'cheese', 'bread', 'tomato'],
    "utilities": ['plates', 'forks', 'spatulas'],
    "guests": ['john', 'matt', 'bill']
  },
  y = ['bacon', 'tomato', 'forks'];

let res = Object.keys(x).reduce((a, b) => {
  if (x[b].some(v => y.includes(v))) a.push(b);
  return a;
}, []);

console.log(res);

For your comment - with var and normal function:

var res = Object.keys(x).reduce(function (a, b) {
    if (x[b].some(function (v) {
            return y.indexOf(v) !== -1;
        })) a.push(b);
    return a;
}, []);
Sign up to request clarification or add additional context in comments.

7 Comments

I would do an && !a.includes(b) check before pushing to a - else it will contains dups
Good thought @tymeJV, but as an object key is unique by definition and some stops at the first hit, I don't think there's a possible duplication. Can you say in which scenario it could happen?
Ahh yeah, nvm - it's looping the keys. It would only happen if you looped y first - nvm :)
@Ackados let is a replacement for var, you can replace it if you intend to use that in a modern browser or you use a transpiler. You can replace the arrow function with function() though. Edited the answer to use a normal function and var
Nice approach, using .reduce().
|
3

You can Array#filter the array of Object#keys using a map of the y array, and Array#some.

var x = {
  "food": ['bacon', 'cheese', 'bread', 'tomato'],
  "utilities": ['plates', 'forks', 'spatulas'],
  "guests": ['john', 'matt', 'bill']
};
var y = ['bacon', 'tomato', 'forks'];
var yMap = y.reduce(function(o, v) { // create a map to save iteration of y on each comparsion
  o[v] = true;

  return o;
}, {});

var result = Object.keys(x).filter(function(key) { // filter the keys
  return x[key].some(function(v) { // keep the key, if at least one item of the array is in the map
    return yMap[v];
  });
});

console.log(result);

And the ES6 version using Set:

const x = {
  "food": ['bacon', 'cheese', 'bread', 'tomato'],
  "utilities": ['plates', 'forks', 'spatulas'],
  "guests": ['john', 'matt', 'bill']
};
const y = ['bacon', 'tomato', 'forks'];
const ySet = new Set(y);

const result = Object.keys(x).filter((key) => x[key].some((item) => ySet.has(item)));

console.log(result);

Comments

1

You can do it using .filter() and .some() methods with Object.keys():

function getContainerName(obj, values) {
  return Object.keys(obj).filter(function(key) {
    return y.some(function(v){
      return obj[key].indexOf(v) !== -1;
    })
  });
}

Demo:

var x = {
    "food": ['bacon', 'cheese', 'bread', 'tomato'],
    "utilities": ['plates', 'forks', 'spatulas'],
    "guests": ['john', 'matt', 'bill']
  },
  y = ['bacon', 'tomato', 'forks'];


function getContainerName(obj, values) {
  return Object.keys(obj).filter(function(key) {
    return y.some(function(v){
      return obj[key].indexOf(v) !== -1;
    })
  });
}
console.log(getContainerName(x, y));

2 Comments

If I added the code correctly, this one resulted in faster speeds. jsperf.com/faster-array-naming
@Ackados I think that's because this one has fewer instructions than the other ones, but they are just different ways to solve the problem, and choosing one of them depends on the situation, and wether you worry or not about performance or readability.

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.