Home > Software design >  Using Lodash to get value by It's key while some keys don't exist
Using Lodash to get value by It's key while some keys don't exist

Time:10-31

How to use Lodash while I am mapping through an array to get and assign the relevant values?

This is what my unfiltered array looks like, I want to extract the ID and name[x].text into an array. But as you can see some objects do not have french text in them, In that case I want to take the English text instead.

const response = {
    "data": {
      "Animals": [
        {
          "id": "1",
          "name": [
            {
              "language": "en-US",
              "text": "Horse"
            }
          ]
        },
        {
          "id": "2",
          "name": [
            {
              "language": "en-US",
              "text": "Pig"
            }
          ]
        },
       {
          "id": "3",
          "name": [
            {
              "language": "en-US",
              "text": "Cat"
            },
            {
              "language": "fr-CA",
              "text": "Un Chat"
            }
          ]
        },
        {
          "id": "4",
          "name": [
            {
              "language": "en-US",
              "text": "Dog"
            },
            {
              "language": "fr-CA",
              "text": "Un Chien"
            }
          ]
        }
      ]
    }
  }


console.log(response.data.Animals.map(animal => animal.name[0].text)); // If I do this I get all the English text, but If I map the same with index of the French, I get undefined error and It crashed my application.

This is more suitable as It returns the French and English text but there are two improvements I want to make,

  1. Get the value from it's key ("en-US" and "fr-CA") so that I know for sure I have the correct value.

  2. I am mapping to populate a table, So I do not need a new array with values because I don't want to lose the index if the parent array, If text it not available it should go find the English text.

  3. This is an extra question but it will help me learn to use Lodash better, Incase I want to set the value(either in En or Fr), how would I do that?

     arr.map((obj) => {
     const id = obj.id;
     const englishtext = _.get(obj, 'name[0].text', 'N/A');
     const frenchtext = _.get(obj, 'name[1].text', englishtext);
     return { id, englishtext, frenchtext };
    

    }

UPDATE: I apologize my question was unclear, to be honest I am a bit confused as well. So here is the expected output I am looking for. So when I map the given variable response, I want an another array that looks like this,

EXPECTED OUTPUT:

[
{
id: 1,
engname: Horse,
frenchname: Horse (because french is not available),
},
.
.
.
{
id:3,
engname:Cat,
frenchname: Un Chat, (because the French array is there this time)
}
.
.
.
and so on.. 
] 

CodePudding user response:

I would post a non-Lodash version of solution because I don't find Lodash necessary in this case. But I know you asked for Lodash solution, so ignore this if you must use Lodash.

If I understand your question correctly, the rule set you want to employ for extracting the values is the following:

  1. If there is a French text, use that regardless of the existence of the English text. Also, the French text always comes after the English text in the array (French text always has the index of -1).

  2. If there is no French text, use the English text (English text is guaranteed to be there for all items).

In that case, I think you could use either Array.prototype.pop() or Array.prototype.at() to achieve what you want.

Array.prototype.pop() solution

response.data.Animals.map(animal => animal.name.pop().text)

Pros:

  • Widely available among all the modern browsers.

Cons:

  • This mutates the original data and changes the length of the original array.

Array.prototype.at() solution

response.data.Animals.map(animal => animal.name.at(-1).text)

Pros:

  • This operation is immutable, so original data is intact.

Cons:

  • Some browsers might not support this.

If you are open to non-Lodash solutions, I suppose you could use one of these.

Update

Thank you @WildThing for updating the question. I think you can use this to achieve the mapping you want:

response.data.Animals.map(animal => {
  engName = animal.name.find(name => name.language === "en-US");
  frenchNameIfExists = animal.name.find(name => name.language === "fr-CA");

  return {
    id: animal.id,
    engname: engName.text,
    frenchname: (frenchNameIfExists || engName).text,
  }
})

CodePudding user response:

May be there is no need lodash:

const toMyArray = (arr, frenchnameCode = "fr-CA", engnameCode = "en-US") => {
  return arr.map(({ id, name }) => {
    const engname = name
      .find(({ language }) => language === engnameCode)
      .text;
    const frenchname =  name
      .find(({ language }) => language === frenchnameCode)
      ?.text;
      
    return { id, engname, frenchname: frenchname ?? engname }
  });
};

console.log(toMyArray(response.data.Animals));

// [
//   {id: '1', engname: 'Horse', frenchname: 'Horse'},
//   {id: '2', engname: 'Pig', frenchname: 'Pig'},
//   {id: '3', engname: 'Cat', frenchname: 'Un Chat'},
//   {id: '4', engname: 'Dog', frenchname: 'Un Chien'},
// ]
  • Related