javascript - Cómo evitar datos duplicados en el bucle for

CorePress2024-01-16  8

Me pregunto cuál es la mejor manera de evitar que datos duplicados entren en una nueva matriz. Tengo una llamada de servicio que devuelve la misma matriz 3 veces. Estoy intentando tomar un número del interior de los objetos de la matriz y sumarlos para crear un número "total". número (fullRentAmt), pero como la matriz se devuelve 3 veces, obtengo el total*3. Estoy pensando que tal vez .some() o .filter() podrían ser útiles aquí, pero nunca los he usado y no estoy seguro de cómo se implementaría aquí. ¡Gracias por cualquier ayuda!

Lo intenté, pero no funciona/la nueva matriz no se completa:

Componente


    properties = [];
    fullRentAmt: number = 0;

            const propertyDataSub = this.mainService.requestPropertyData()
              .subscribe((pData: PropertyData[]) => {
                if (pData) {
                  const propertyData = pData;
                  for (let i = 0; i < propertyData.length; i++) {
                    if (this.properties[i].propertyId !== propertyData[i].propertyId) {
                      this.properties.push(propertyData[i]);
                    }
                  }
                  for (let i = 0; i < this.properties.length; i++) {
                    this.fullRentAmt += this.properties[i].tenancyInformation[0].rentAmount;
                  }
              });

Datos devueltos desde el backend (matriz de 2 objetos):


[
   {
      "tenantsData":[
         {
            "email":null,
            "tenantNames":null,
            "propertyId":2481,
         }
      ],
      "tenancyInformation":[
         {
            "id":2487,
            "rentAmount":1000,
         }

      ],
   },
   {
      "tenantsData":[
         {
            "email":null,
            "tenantNames":null,
            "propertyId":3271,
         }
      ],
      "tenancyInformation":[
         {
            "id":3277,
            "rentAmount":1200,
         }

      ],
   },

Pero ¿por qué el Backend lo devuelve 3 veces? ¿Es una solicitud 3 veces de Angular? ¿O un error del Backend?

-yazantahhan

19/03/2021 a las 20:37



------------------------------------

No soy un desarrollador angular, pero espero que mi respuesta te ayude.

deje que el bucle for duplique los datos tanto como quiera. sólo tienes que cambiar la idea de almacenar el material de una matriz a un conjunto de JavaScript

básicamente, es muy similar a los arreglos: son listas e iterables que son muy similaresa los arrays, la única diferencia es que no permiten la duplicación,

uso:

const properties = new Set()
properties.add("yellow")
properties.add("blue")
properties.add("orange")
console.log(properties) // yellow, blue, orange

properties.add("blue") 
properties.add("blue") 
properties.add("blue") 
console.log(properties) // yellow, blue, orange

después de que finalice el bucle for, es posible que quieras convertir este conjunto en una matriz normal, todo lo que tienes que hacer es usar la desestructuración:

const propertiesArray = [...properties]



------------------------------------

@YaYa tiene razón. Agregué esto para mostrar el código correcto en Angular

properties = [];
fullRentAmt: number = 0;

const propertyDataSub = this.mainService.requestPropertyData()
  .subscribe((pData: PropertyData[]) => {
    if (pData && pData.length) {
      let arrSet = new Set()
      const propertyData = pData;
      for (let i = 0; i < propertyData.length; i++) {
        if (this.properties[i].propertyId !== propertyData[i].propertyId) {
          arrSet.add(propertyData[i])
        }
      }
      this.properties = Array.from(arrSet);

      for (let i = 0; i < this.properties.length; i++) {
        this.fullRentAmt += this.properties[i].tenancyInformation[0].rentAmount;
      }
  });



------------------------------------

Lo primero que debes hacer es arreglar tu servidory devolver la lista una vez.

Si el servidor está fuera de su alcance, puede aprovechar la canalización distintaUntilChanged en combinación con el método isEqual en la interfaz. Puede implementarlo usted mismo o utilizar una biblioteca como lodash.

Además, no es necesario que se suscriba; utilice una canalización asíncrona en la plantilla.

this.properties$ = this.mainService.requestPropertyData()
  .pipe(
    distinctUntilChanged(isEqual) // provide isEqual function somehow
  );
this.totalRentAmount$ = properties$.pipe(
  map(getTotalRentAmount)
);

// maybe in some other utility file:
export const getTotalRentAmount = (properties: Property[]): number => {
  return properties
    .map(property => property.tenancyInformation.rentAmount)
    .reduce((total, amount) => total + amount, 0);
}

Luego en la plantilla:

<div>Total Rent Amount: {{ totalRentAmount | async }}</div>

Además, si realmente necesita suscribirse al componente y solo está interesado en el primer valor emitido de un observable, puede usar la tubería first() o take(1) para cancelar la suscripción automáticamente después del primer valor.

this.mainService.requestPropertyData()
  .pipe(
    first() // or take(1)
  )
  .subscribe(properties => this.properties = properties);

Vea la diferencia entre first() y take(1)

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare