Home > Software engineering >  Vue JS - remove repeating data in the vue component
Vue JS - remove repeating data in the vue component

Time:08-27

I have lots of results that display from a component. Im having problems with the location data which I want to display in the component. Its sitting as multiple elements with | to separate them. How do I filter down to remove all duplicates in each result and display it as a comma separated list.

I would like the data to appear from the component

Title: Holiday One Location:AZ,FL,TX,MA,AZ,MS,TN,AL

Title: Holiday two Location:TN,AZ,FL,AL

Title: Holiday three Location:AZ,NY,WY,TN,FL, AL

The main page

<result
 v-for="(result, index) in results"
 :result="result"
 :index="index"              
 />

This is the result component.

<template>
  <div>
    <div v-if="location">{{ location }}
 </div>

<script>
export default {
  name: "result",
  
  props: {
    result: Object,
  },
  data: function () {
    return {
      location: this.result.location,
  </script>   

JSON

"results": {
"title": "Holiday one",
"location": "AZ|AZ|FL|TX",
"location": "MA|AZ|MS|TX",
"location": "TN|AZ|FL|AL",
"date": "22/08/2022",
},
"results": {
"title": "Holiday two",
"location": "TN|AZ|FL|AL",
"date": "20/08/2022",
},
"results": {
"title": "Holiday three",
"location": "AZ|NY|NY|WY",
 "location": "TN|AZ|FL|AL",
"date": "10/08/2022",
},
"results": {
"title": "Holiday four",
"location": "MA|AZ|MS|TX",
"location": "TN", 
 "location": "CN", 
"date": "14/08/2022",
},
"results": {
"title": "Holiday five",
"location": "CL|VT|NB|TX",
"location": "RI|NH ",
 "location": "TX",
 "location": "SC|NC",
"date": "18/08/2022",
},

Any help appreciated

CodePudding user response:

  1. Convert string to array. Use String.prototype.split() to create an array from a string using '|' as the delimiter.

  2. Remove duplicates. There are many ways you can choose to remove duplicates, one easy way is to convert an array to a Set which can only contain unique values, then convert back to an array.

  3. Convert back into comma separated string. Array.prototype.join() will convert an array to a string using whatever delimiter you'd like.

A one liner of all three steps would look like this:

const nonDuplicateLocations = Array.from(new Set(results.location.split('|'))).join(',')

CodePudding user response:

First of all, your JSON is invalid. You can't specify a key more than once on the same object. You'll get an error. Since you seem to have multiple holidays, you might want to use an array, not an object.
For the same reason, inside each Holiday, you might want to use a locations array.

So your data should probably look like this:

{
  "results": [
    {
      "title": "Holiday one",
      "locations": ["AZ|AZ|FL|TX", "MA|AZ|MS|TX", "TN|AZ|FL|AL"],
      "date": "22/08/2022"
    },
    {
      "title": "Holiday two",
      "locations": ["TN|AZ|FL|AL"],
      "date": "20/08/2022"
    },
    {
      "title": "Holiday three",
      "locations": ["AZ|NY|NY|WY", "TN|AZ|FL|AL"],
      "date": "10/08/2022"
    },
    {
      "title": "Holiday four",
      "locations": ["MA|AZ|MS|TX", "TN", "CN"],
      "date": "14/08/2022"
    },
    {
      "title": "Holiday five",
      "locations": ["CL|VT|NB|TX", "RI|NH ", "TX", "SC|NC"],
      "date": "18/08/2022"
    }
  ]
}

Now, with the above data, my understanding is that you want to collect all the 2-letter codes from each location, remove duplicates and display them comma separated. I'm guessing sorting wouldn't hurt, either.
Here's how you could do it:

const results = [
  {
    title: "Holiday one",
    locations: ["AZ|AZ|FL|TX", "MA|AZ|MS|TX", "TN|AZ|FL|AL"],
    date: "22/08/2022",
  },
  {
    title: "Holiday two",
    locations: ["TN|AZ|FL|AL"],
    date: "20/08/2022",
  },
  {
    title: "Holiday three",
    locations: ["AZ|NY|NY|WY", "TN|AZ|FL|AL"],
    date: "10/08/2022",
  },
  {
    title: "Holiday four",
    locations: ["MA|AZ|MS|TX", "TN", "CN"],
    date: "14/08/2022",
  },
  {
    title: "Holiday five",
    locations: ["CL|VT|NB|TX", "RI|NH ", "TX", "SC|NC"],
    date: "18/08/2022",
  },
];
new Vue({
  el: "#app",
  data: () => ({
    holidays: results,
  }),
  methods: {
    renderLocations(h) {
      return [...new Set(h.locations.join("|").split("|"))].sort().join(", ");
    },
  },
});
dl:not(:last-child) {
  border-bottom: 1px solid #ddd;
  padding-bottom: 1rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.10/vue.min.js"></script>
<div id="app">
  <dl v-for="(holiday, index) in holidays" :key="index">
    <dt>Title</dt>
    <dd v-text="holiday.title"></dd>
    <dt>Locations</dt>
    <dd v-text="renderLocations(holiday)"></dd>
    <dt>Date</dt>
    <dd v-text="holiday.date"></dd>
  </dl>
</div>

Let's take renderLocations apart:

  • takes all the location entries of holiday arg (h.locations)
    =>["AZ|AZ|FL|TX", "MA|AZ|MS|TX", "TN|AZ|FL|AL"]
  • glues them in a single string, using | as separator (.join('|'))
    => "AZ|AZ|FL|TX|MA|AZ|MS|TX|TN|AZ|FL|AL"
  • unglues the string in a strings array, using | as separator (.split('|'))
    => ["AZ", "AZ", "FL", "TX", "MA", "AZ", "MS", "TX", "TN", "AZ", "FL", "AL"]
  • removes duplicates from the array - the ([ ...new Set( )]) wrapper
    => ["AZ", "FL", "TX", "MA", "MS", "TN", "AL"]
  • sorts them alphabetically .sort()
    => ["AL", "AZ", "FL", "MA", "MS", "TN", "TX"]
  • glues them into a string, using , as separator (.join(', '))
    => "AL, AZ, FL, MA, MS, TN, TX"

Same example as above, using Vue 3 and a dedicated <Holiday /> component:

const results = [
  {
    title: "Holiday one",
    locations: ["AZ|AZ|FL|TX", "MA|AZ|MS|TX", "TN|AZ|FL|AL"],
    date: "22/08/2022",
  },
  {
    title: "Holiday two",
    locations: ["TN|AZ|FL|AL"],
    date: "20/08/2022",
  },
  {
    title: "Holiday three",
    locations: ["AZ|NY|NY|WY", "TN|AZ|FL|AL"],
    date: "10/08/2022",
  },
  {
    title: "Holiday four",
    locations: ["MA|AZ|MS|TX", "TN", "CN"],
    date: "14/08/2022",
  },
  {
    title: "Holiday five",
    locations: ["CL|VT|NB|TX", "RI|NH ", "TX", "SC|NC"],
    date: "18/08/2022",
  },
];

const { createApp, defineComponent } = Vue;

const Holiday = defineComponent({
  template: "#holiday-tpl",
  props: ["holiday"],
  setup: () => ({
    renderLocations: (a) =>
      [...new Set(a.join("|").split("|"))].sort().join(", "),
  }),
});

const App = createApp({
  components: { Holiday },
  setup: () => ({
    holidays: results,
  }),
});

App.mount("#app");
dl:not(:last-child) {
  border-bottom: 1px solid #ddd;
  padding-bottom: 1rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.37/vue.global.prod.min.js"></script>
<div id="app">
  <Holiday v-for="(holiday, index) in holidays"
           :key="index"
           :holiday="holiday" />
</div>
<template id="holiday-tpl">
  <dl>
    <template v-for="(value, name) in holiday">
      <dt
        :key="`dt-${name}`"
        v-text="name.charAt(0).toUpperCase()   name.slice(1)"
      />
      <dd
        :key="`dd-${name}`"
        v-text="name === 'locations' ? renderLocations(value) : value"
      />
    </template>
  </dl>
</template>

  • Related