Search code examples
javascriptarraysobject

Javascript Advanced Array Manipulation


Given a truncated array of object

const catsData = [
    {
        emotionTags: ["moody"],
        isGif: false,
        image: "angry.jpeg",
        alt: "A cat looking moody",
    },
    {
        emotionTags: ["moody", "insomniac"],
        isGif: false,
        image: "angry2.jpeg",
        alt: "A cat looking moody",
    },
    {
        emotionTags: ["moody"],
        isGif: false,
        image: "angry3.jpeg",
        alt: "A cat looking moody",
    },
    {
        emotionTags: ["confused", "sad"],
        isGif: false,
        image: "confused.jpeg",
        alt: "A cat looking confused",
    }]

I would love to transform it into an array like below:

    {
        emotionTags: 'moody',
        isGif: false,
        image: ["angry.jpeg", 'angry2.jpeg','angry3.jpeg', 'sad1.jpeg'],
        alt: ['A cat looking moody', 'A cat looking sad']
    },
    {
        emotionTags: 'insomniac',
        isGif: false,
        image: ['angry2.jpeg', 'insomnia.jpeg', 'insomnia1.jpeg'],
        alt: ['A cat looking moody', 'A cat looking insomniac',]
    },
    {
        emotionTags: 'confused',
        isGif: false,
        image: ['confused.jpeg'],
        alt: ['A cat looking confused']
    }
]

Such that all images that corresponds to a particular mood are grouped in an array of images (same with their alt if possible). images that correspond to more than one mood can also be grouped in that particular's mood object too.

I tried doing the below:

 let emotions = ['moody','insomniac','confused','sad','dominant','hungry','relaxed','angry']

 let modCatData = catsData.reduce((allCat, cat,idx)=>{
  let imageArr = []
  if(cat['emotionTags'].includes (emotions[idx])){
    imageArr.push(cat.image)
    allCat.push({
      'image':imageArr
    })
  }
  else{
    allCat.push({
      'image':cat.image
    })
  }
  return allCat
  
},[])

console.log(modCatData)ere

I was hoping to be able to pick an emotion, test it against the object emotions, and grouped the images that correspond with it, but i have difficulty grouping the images so far.

would appreciate a solution or direction if possible.


Solution

  • Firstly, the input you provided has no sentences like, "A cat looking insomniac" or "A cat looking sad" but your output includes those sentences. So, not sure what is your correct data.

    Second, if I got your question correctly then you want to create an array of moods and group the images and alts of that particular mood in that single mood item. So you might try the following-

    1. Run loop on mood array.
    2. Filter which items are having the current mood.
    3. Get the images and alts from the filtered items using the map function.
    4. I used the Set operator to filter the unique images and alt in case of duplicity.

    Here is the demo-

    const catsData = [{
        emotionTags: ["moody"],
        isGif: false,
        image: "angry.jpeg",
        alt: "A cat looking moody",
      },
      {
        emotionTags: ["moody", "insomniac"],
        isGif: false,
        image: "angry2.jpeg",
        alt: "A cat looking moody",
      },
      {
        emotionTags: ["moody"],
        isGif: false,
        image: "angry3.jpeg",
        alt: "A cat looking moody",
      },
      {
        emotionTags: ["confused", "sad"],
        isGif: false,
        image: "confused.jpeg",
        alt: "A cat looking confused",
      }
    ];
    
    let emotions = ['moody', 'insomniac', 'confused', 'sad', 'dominant', 'hungry', 'relaxed', 'angry']
    
    let final = [];
    
    emotions.forEach(e => {
      let obj = {}
      let result = catsData.filter(cd => cd.emotionTags.includes(e))
      obj.emotionTags = e;
      obj.isGif = false;
      obj.image = [...new Set(result.map(item => item.image))]
      obj.alt = [...new Set(result.map(item => item.alt))]
      final.push(obj)
    })
    
    console.log(final)

    Let me know if your data is something different, I will update the answer.