Home > database >  How to push each value of array inside object to another array with vue using foreach?
How to push each value of array inside object to another array with vue using foreach?

Time:01-25

I'm trying to create an array from items inside objects, as well as items inside arrays inside objects in a vue app, by using foreach to loop over them. It works well when I only have one single item, but I can't figure out how to loop over an array inside the object and add all of those items to the array I'm creating.

What I have now


const examples = [
    {
        name: "Example 1",
        type: ["Meat", "Water", "Dairy"],
        showDetail: false
    },
    {
        name: "Example 2",
        type: Fruit,
        showDetail: false
    },
{
        name: "Example 3",
        type: Vegetable,
        showDetail: false
    }
]


new Vue({
    data: {
        examplesList: examples,
        type: ''
    },
    methods: {
        filterList: function() {
            this.type = event.target.value;
        }
    },
    computed: {
        uniqueList: function() {
            const types = [];
            this.examplesList.forEach((example) => {
                if (!types.includes(example.type)) {
                    types.push(example.type);
                }
            });
            return types;
        }
    }
})

It works fine if I remove the object with the array inside of "type", and adds the Fruit and Vegetable items to the array. Any ideas?

Desired output:

["Meat", "Water", "Dairy", "Fruit", "Vegetable"]

CodePudding user response:

Here is one possible solution. You'll need to translate the solution to vue, of course, but the problem here really doesn't have anything to do with vue specifically so I've shown a vanilla javascript solution just to keep things simple.

const examples = [
  {
    name: "Example 1",
    type: ["Meat", "Water", "Dairy", "Fruit"],
    showDetail: false
  },
  {
    name: "Example 2",
    type: "Fruit",
    showDetail: false
  },
  {
    name: "Example 3",
    type: "Vegetable",
    showDetail: false
  }
];

const types = [];
examples.forEach((example) => {
  const exampleTypes = Array.isArray(example.type)
    ? example.type
    : [example.type];
  for (let exampleType of exampleTypes) {
    if (!types.includes(exampleType)) {
      types.push(exampleType);
    }    
  }
});

console.log(types);

CodePudding user response:

Here's an abstract way of doing that using a Set. Sets guarantee unique values meaning there's no need to check if an item is present or not.

Using just an array will become increasingly expensive to check if an item was already added as it will have to scan the entire array for each includes, O(n) time complexity.

const examples = [{
    name: "Example 1",
    type: ["Meat", "Water", "Dairy"],
    showDetail: false
  },
  {
    name: "Example 2",
    type: "Fruit",
    showDetail: false
  },
  {
    name: "Example 3",
    type: "Vegetable",
    showDetail: false
  }
];

const typeSet = new Set();
let types;
examples.forEach((example) => {
  if (Array.isArray(example.type)) {
    example.type.forEach(type => {
      typeSet.add(type);
    });
  } else {
    typeSet.add(example.type);
  }
});
types = [...typeSet];

console.log(types);

CodePudding user response:

Here is one possible solution to achieve the desired result:

computed: {
    uniqueList: function() {
        return this.examplesList.reduce(
          (acc, itm) => (
            Array.isArray(itm.type)
            ? itm.type.filter(t => !acc.includes(t)).length > 0
              ? [
                  ...acc,
                  ...itm.type.filter(t => !acc.includes(t))
                ]
              : acc
            : acc.includes(itm.type)
              ? acc
              : [...acc, itm.type]
          ), []
        )
    }
}

Explanation

  1. reduce is used on the array this.examplesList
  2. Each item itm is processed and acc is the accumulator/aggregator (initially set to an empty array [])
  3. if itm.type is an Array, then
  • if any elements in itm.type array is not already present in acc array, include it (by using the ... spread operator)
  1. otherwise (ie, itm.type is a string)
  • if it is not already in acc, then include it (again, using ... spread operator)

That's it !

Please comment if any further clarification/s or question/s.

Code snippet

const examples = [{
    name: "Example 1",
    type: ["Meat", "Water", "Dairy"],
    showDetail: false
  },
  {
    name: "Example 2",
    type: "Fruit",
    showDetail: false
  },
  {
    name: "Example 3",
    type: "Vegetable",
    showDetail: false
  }
];

const getUniqueTypes = (arr = examples) => (
  arr.reduce(
    (acc, itm) => (
      Array.isArray(itm.type)
      ? itm.type.filter(t => !acc.includes(t)).length > 0
        ? [
            ...acc,
            ...itm.type.filter(t => !acc.includes(t))
          ]
        : acc
      : acc.includes(itm.type)
        ? acc
        : [...acc, itm.type]
    ), []
  )
);

console.log(getUniqueTypes());

  •  Tags:  
  • Related