Ionic 4 Filter Unique Data With Pipe

So, I want to filter an api response, unique data only based on project id, but the project id is deep down inside the array.

I’ve made a pipe but its not filtering unique data.instead it filter based on the inputted parameter.

  filterProject(myProject: any) {
return myProject.project.target / myProject.project.total == 1; }

now I want to create a pipe to filter the unique data based on project id. here’s the data structure:

Thanks in Advance!

I don’t understand correctly what data you want to filter because you say you want to filter a single data?
One of the whole arrangement you have?

You have to have a criterion to filter a specific data or the easiest to filter by the position in the data array.

Tell me more about what criteria the data you want to filter has, that is why you want to extract only one of the whole array

I would strongly suggest not doing this. Heavy operations like filtering and ordering are a bad fit for pipes, because they get called too often. Instead do the filtering in your controller.

I think that depends on the code’s best practice.

A few months ago I made a pipe for a very heavy search that sometimes searches up to 50,000 different data sheets in a single search and sometimes took a maximum of 5.6 seconds to perform the exact search on this large amount of data.

This is the code of the pipe i created.

import { Pipe, PipeTransform } from '@angular/core';
import * as _ from 'lodash';
@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {
  transform(items: any[], searchText: string): any[] {
    let data: any[] = [];
    var chars = {
      "á": "a", "é": "e", "í": "i", "ó": "o", "ú": "u",
      "à": "a", "è": "e", "ì": "i", "ò": "o", "ù": "u",
      "Á": "A", "É": "E", "Í": "I", "Ó": "O", "Ú": "U",
      "À": "A", "È": "E", "Ì": "I", "Ò": "O", "Ù": "U"
    }
    var remplazador = /[áàéèíìóòúùñ]/ig;
    if (!items) {
      return [];
    }
    if (!searchText) {
      return items;
    }
    let comparador = String(searchText).replace(remplazador, function(valor) { return chars[valor] })
    comparador = comparador.replace(/[^0-9A-Za-z]/g, '')
    comparador = comparador.toLowerCase()
    items.forEach(i => {
      Object.keys(i).forEach(async function(k, v) {
        let posicion = String(i[k]).replace(remplazador, function(valor) { return chars[valor] })
        posicion = posicion.replace(/[^0-9A-Za-z]/g, '')
        if (await _.includes(String(posicion).toLowerCase(), comparador)) {
          if (!data.includes(i)) {
            data.push(i)
          }
        }
      });
      if (i["atributos"]) {
        try {
          i["atributos"].forEach(j => {
            Object.keys(j).forEach(async function(k, v) {
              let posicion = String(j[k]).replace(remplazador, function(valor) { return chars[valor] })
              posicion = posicion.replace(/[^0-9A-Za-z]/g, '')
              if (await _.includes(String(posicion).toLowerCase(), comparador)) {
                if (!data.includes(j)) {
                  data.push(i)
                }
              }
            });
          })
        } catch (e) { }
      }
    })
    return data
  }
}

The pipeline is about results with many more than 5 levels within itself and is searched by all types of cemeteries that each one has inside, it is also worth mentioning that the variables are Spanish as it is done in this language by practice for my other co-workers who do not have much knowledge or are not very familiar with the keys to data arrangements in English
Maybe you can read it and try to understand it and you will see that the performance is very good

And this is used in an ngFor that changes dynamically according to the text that is entered in the search bar and the filter pipe is activated.

You can use the exact same implementation. I’m just suggesting that you call it from controllers instead of templates, or take over all the minutiae of change detection yourself. This exact issue is why Angular dropped the filter pipe in v2.

so I got some same data from the api response. I want to show each data once only, and filter it by the project.id.

34

sorry, English is not my mother language.

Try this.
DATA= this variable is an example created with the keys that you have in your variable to be able to exemplify you with this filter you can return the data that you want to contain the varlor of the project that you want

 data=[ 
    {
      amount:"2544",
      project:{
        category:"restaurant",
        id:4
      }
    },
    {
      amount:"157565",
      project:{
        category:"home",
        id:52
      }
    }
  ]


constructor() {
    this.filterUnique(this.data)
  }


  async filterUnique(array){
    array=await array.filter(item=> item.project.id==4)
    console.log(array) //ouput only unique item 
  }

Thanks for still replying!

 data=[ 
    {
      amount:"2544",
      project:{
        category:"restaurant",
        id:4
      }
    },
    {
      amount:"157565",
      project:{
        category:"home",
        id:52
      }
    },
    {
      amount:"251244",
      project:{
        category:"restaurant",
        id:4
      }
  ]

what I meant is I want to get both id: 52 and id:4, but since there are two id:4, I want to filter it so there will be only one id:4

in case you have two id: 4 you would have to use another field to make the filter, then this means that you use 2 fields for the filter
For example using amout and id project

data=[ 
    {
      amount:"2544",
      project:{
        category:"restaurant",
        id:4
      }
    },
    {
      amount:"157565",
      project:{
        category:"home",
        id:52
      }
    },
    {
      amount:"251244",
      project:{
        category:"restaurant",
        id:4
      }
    }
  ]

constructor() {
    this.filterUnique(this.data)
  }

 async filterUnique(array){
    array=await array.filter(item=> item.project.id==4 && item.amount=='251244')
    console.log(array) //ouput only unique item 
  }

and you would have to add another level to be able to make the filter when it is two or more data that you want to return, and if you want it to return only one of those that are repeated the same you have to apply an extra filter.

thank you for the reply, but I just found a better solution by using ‘uniqBy()’ from lodash.

https://lodash.com/docs/4.17.15#uniqBy