Как отфильтровать данные во вложенном массиве в Angular - PullRequest
0 голосов
/ 09 июля 2020

У меня есть служба Angular, которая отправляет вызов службы данных и возвращает массив объектов, содержащих несколько уровней данных. Я хочу иметь возможность фильтровать эти данные и возвращать только тот объект, который содержит определенное c значение.

        this.service.getRecords().pipe(
        map(item => item.filter(items => items.attributes['identifier'].value === '101723102')),
        tap(item => console.log(item)),

    ).subscribe();

Атрибуты [] содержат множество объектов, подобных указанному ниже:

[20000]: {identifier:"1239213", something: "42142", something: "42142", something: "42142".....}

Я пытаюсь отфильтровать и вернуть объекты, если идентификатор чему-то равен, но я не уверен, как получить доступ к значению, поскольку оно вложено, и я не могу использовать точечную нотацию. Текущий код возвращает ошибку: Cannot read property 'identifier' of undefined

[EDIT]: это служба, которую я использую

export class DataViewerService {

_recordDetails: Observable<DataClass[]>;

// служба ресурсов содержит код для извлечения конструктора данных (private _resourceService: ResourceService, ) {}

    getRecords() {
    return this._recordDetails = this._resourceService.search(CONSTANT, {})
        .pipe(map(extractRecords))
        .pipe(shareReplay()) as Observable<Data[]>;

}


function extractRecords(result) {
const records = [];
if (!isNullOrUndefined(result)) {
    result.forEach(r => {
        if (!isNullOrUndefined(r['payload'])) {
            records.push(r.payload);
        }
    });
}
return records;

}

[EDIT]: Items Объект выглядит следующим образом:

{
  attributes: [],
  descrtiption: "",
  name: "",
  label: ""
}

I need to access the objects within the attributes[] of filter which looks like
attributes: [
{
     identifier: "1243212",
     something: "",
...
}

Это интерфейс, а возвращаемый объект имеет тип Data.

export interface Data {
name: string;
label: string;
attributes: DataAttributes[];

}

interface DataAttributes {
    attributes: [
           identifier: string;
           something: string;
     ];
    something: string;
...
 
}

И служба возвращает атрибуты [], которые содержат значения, которые я хочу отфильтровать

Ответы [ 4 ]

1 голос
/ 09 июля 2020

Это может сработать

map(item => item.filter(items => items.attributes['identifier'] && items.attributes['identifier'].value === '101723102')),

или

map(item => item.filter(items => item.attributes !== undefined && items.attributes['identifier'] != undefined && items.attributes['identifier'].value === '101723102'))

, также будет лучше, если вы отредактируете DataAttributes следующим образом:

interface DataAttributes {
    name: string;
    label: string;
    identifier?: any;
}
0 голосов
/ 09 июля 2020

Очень непонятно, что именно вы пытаетесь сделать. Предполагая, что ваша цель - взять ваши Data объекты и выбрать определенные DataAttributes объекты, которые соответствуют некоторому имени, вы можете сделать что-то вроде этого:

  1. сопоставьте каждый Data элемент с его массивом attributes
  2. сводит эти массивы атрибутов к единому потоку DataAttributes объектов
  3. фильтрует эти DataAttributes объекты по желаемому name
const records: Observable<Data[]> = ...;
const selectAttribute = 'some name';
records.pipe(
  concatMap(records => records.map(({attributes}) => attributes)),
  concatAll(),
  filter(({name}) => name === selectAttribute)
);

https://stackblitz.com/edit/so-62805815

0 голосов
/ 09 июля 2020

Если вы не против не иметь для этого алгоритма, вы можете положиться на loda sh для подобных операций с объектами в Javascript (не Angular как таковом).

Первый install loda sh (npm install lodash).

Поскольку вы хотите фильтровать по вложенному ключу, вы должны использовать метод filter с функцией в качестве предиката.

import * as _ from 'lodash';

// let's asume a variable called attributes holds your array of objects
const filteredData = _.filter(attributes, function(item) { return item.value === 'something'; })

I не знаю, понимаю ли я структуру ваших данных. Вы можете прочитать документацию для filter здесь .

0 голосов
/ 09 июля 2020

Использование интерфейса новой модели следующим образом

export interface DataModel {
  name: string;
  label: string;
  attributes: object[];
}

Использование фиктивных данных следующим образом

{
    attributes: [
        { identifier: '1239213', something: 100 },
        { identifier: 'foo', someOtherThing: 100},
        { identifier: '101723102', description: "101723102"},
        { notIdentifier: '101723102', description: "101723102"}        
    ],
    name: "",
    label: ""
}

Использование Mock Data Service следующим образом

import { Injectable } from '@angular/core';
import { Subject, BehaviorSubject } from 'rxjs';
import { DataModel } from './models/data';

@Injectable()
export class DataService {

  private mockData : DataModel = {
    attributes: [
        { identifier: '1239213', something: 100 },
        { identifier: 'foo', someOtherThing: 100},
        { identifier: '101723102', description: "101723102"},
        { notIdentifier: '101723102', description: "101723102"}    
    ],
    name: "",
    label: ""
  }

  private sbj : BehaviorSubject<{}> = new BehaviorSubject<any>(this.mockData);
  constructor() { }

  getRecords() {
    return this.sbj;
  }
}

Выполните следующие действия

import { Component, VERSION, OnInit } from '@angular/core';
import { DataService } from './data.service';
import { map, tap } from 'rxjs/operators';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
  name = 'Angular ' + VERSION.major;

  public filteredObjStr = ''
  constructor(private service: DataService) {

  }

  ngOnInit() {
    this.service.getRecords().pipe(
        map(item =>   {
          if (item['attributes'] == null) {
            return []
          }
          return item['attributes'].filter(x => x['identifier'] === '101723102')
        }),
        tap(filteredAttribs => 
        {
          this.filteredObjStr = JSON.stringify(filteredAttribs, null, 2);
          console.log('filteredAttribs : ', filteredAttribs);
        })

    ).subscribe();
  }

  public filter_changed(value) {
    console.log(value)
  }
}

Пример - проверьте консоль приложения

https://stackblitz.com/edit/angular-ivy-uvxxjk

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...