0

I have 2 arrays.

One array contains some people objects, the other array contains objects with name key that holds the value needed from the people objects.

My solution so far but not getting any luck....

When mapping over people array how do I return only certain properties from person? Not the entire person object

const customContactValues = people.map((person) => { return valuesNeeded.filter((el) => (el.name in person) ? person[el.name] : ""  ) })

console.log(customContactValues)

Here is my people array

    const people = [
    {
        "foods": {
            "favoriteFood": "Ice cream"
        },
        "firstName": "John",
        "lastName": "Doe",
        "age": 30

    },
    {
        "foods": {
            "favoriteFood": "pizza"
        },
        "firstName": "Jane",
        "lastName": "Doe",
        "age": 39
    },
    {
        "foods": {
            "favoriteFood": "pbj"
        },
        "firstName": "Kevin",
        "lastName": "Baker",
        "age": 22

    },
    {
        "foods": {
            "favoriteFood": "pushpops"
        },
        "firstName": "ernie",
        "lastName": "duncan",
        "age": 29
    },
]

Here is the values array which contains the keys I need from people array

const valuesNeeded = [ 
  { name: 'firstName' },
  { name: 'lastName' },
  { name: 'favoriteFood' }
]

I am trying to get and output like this below

const desiredResult = [
{firstName: "John", lastName: "Doe", favoriteFood: "Ice cream"},
{firstName: "Jane", lastName: "Doe", favoriteFood: "Pizza"},
{firstName: "Kevin", lastName: "Baker", favoriteFood: "pbj"},
{firstName: "ernie", lastName: "duncan", favoriteFood: "pushpops"}
]

1
  • filter just returns the value if the test is true, so is the wrong method, likely you want reduce so that you build a new array of objects with just the properties you want. When you hit an object in the person object (e.g. foods), you need to dig into it looking for el.name. Commented Mar 28, 2022 at 3:56

2 Answers 2

1

filter only filters elements from array based on some condition but in your case we don't want to filter elements we just want to create new array of objects from and existing array so map function is a good start.

Second problem is the object can contain nested object which may contain required key value pair so to retrieve them we can recursively look over the value which is object if we don't find the key value directly in the object.

And since we don't want all the key value for each object in array we can either create a new object or delete from existing object, keeping the original is good and safe option if required for further processing.

const people = [{
    "foods": {
      "favoriteFood": "Ice cream"
    },
    "firstName": "John",
    "lastName": "Doe",
    "age": 30

  },
  {
    "foods": {
      "favoriteFood": "pizza"
    },
    "firstName": "Jane",
    "lastName": "Doe",
    "age": 39
  },
  {
    "foods": {
      "favoriteFood": "pbj"
    },
    "firstName": "Kevin",
    "lastName": "Baker",
    "age": 22

  },
  {
    "foods": {
      "favoriteFood": "pushpops"
    },
    "firstName": "ernie",
    "lastName": "duncan",
    "age": 29
  },
];

// function to retrieve the key value recursively
function valueByKey(obj, key) {
  let value = obj[key];
  if (value) {
    return value;
  }
  Object.keys(obj).forEach(function(k) {
    if (typeof obj[k] == 'object') {
      value = valueByKey(obj[k], key);
    }
  });
  return value;
}

const valuesNeeded = [{
    name: 'firstName'
  },
  {
    name: 'lastName'
  },
  {
    name: 'favoriteFood'
  }
];

// creating new object by passing the current object and key
let output = people.map(function(item) {
  let result = {};
  valuesNeeded.forEach(function(obj) {
    result[obj.name] = valueByKey(item, obj.name);
  });
  return result;
});

console.log(output);

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

7 Comments

@Chandan That looks so clean but there is one slight problem if the value is falsy ('' or 0), your function will return undefined which might not be the expected value. It works perfectly for this example though. HBD @ErikaPeterson007!
@DeveshShukla you are right if the key is not present and ErikaPeterson007 didn't mention what he wanted in that case so I left it with undefined value and let ErkaPeterson007 adjust according to his/her requirement, maybe he don't want to add the key if no value is present then he/she just need to add one extra condition for the case
This is great! Im having little issue though, the valuesNeeded.forEach is throwing the expected assignment or function call instead saw expression error on my end.
@ErikaPeterson007 please can you add the snippet how you are using
Hey Chandan, My issue was fixed by adding const newVar = valuesNeeded.forEach..... The entire snippet you provided works fine in a regular js html project. When I added it to a React app I got the error and needed to assign the forEach as a const. I will add the snippet
|
0

You can search for the desired key on the top level, and go to child objects if not found. Here is my approach :

function getValue(obj, key) {
    const keys = Object.keys(obj);
    // Check if key exist on this level
    if (keys.includes(key)) {
        return obj[key];
    } else {
        // else we try to find in child objects
        for (k of keys) {
            if (typeof obj[k] == 'object') {
                return getValue(obj[k], key);
            }
        }
    }
    //Return this if not found
    return '';
}

const people = [
    {
        foods: {
            favoriteFood: 'Ice cream',
        },
        firstName: 'John',
        lastName: 'Doe',
        age: 30,
    },
    {
        foods: {
            favoriteFood: 'pizza',
        },
        firstName: 'Jane',
        lastName: 'Doe',
        age: 39,
    },
    {
        foods: {
            favoriteFood: 'pbj',
        },
        firstName: 'Kevin',
        lastName: 'Baker',
        age: 22,
    },
    {
        foods: {
            favoriteFood: 'pushpops',
        },
        firstName: 'ernie',
        lastName: 'duncan',
        age: 29,
    },
];

const valuesNeeded = [
    { name: 'firstName' },
    { name: 'lastName' },
    { name: 'favoriteFood' },
];

let output = people.map((item) => {
    let result = {};
    valuesNeeded.forEach(function (obj) {
        result[obj.name] = getValue(item, obj.name);
    });
    return result;
});

console.log(output);

Edit 1 : You can further simplify valuesNeeded to keysNeeded and store only the keys in an array like this keysNeeded = ['firatName', 'lastName', 'favoriteFood']. Please change invocation accordingly.

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.