sebastian sledz
sebastian sledz

Reputation: 49

How to ignore some objects when filter an array

I have an array returnedDocs in code below (shortened via let returnedDocs = result.application.modules.module.moduleItem;) that I got as response from API, it structure is pretty complex. Some nested objects are arrays some values are placed few levels deep in the structure.

I use filter method to get only those elements that got specific value.

          let toFilterSix = returnedDocs.filter(
            o =>
              o.repeatableGroup.repeatableGroupItem.vocabularyReference
                .vocabularyReferenceItem.formattedValue._text === "Abdomen"
          );
          this.filterArray6 = toFilterSix;

Normally it works fine but in below example one of repeatableGroupItem is an array with two elements (image).

arrayInArray

I've got an error due to fact that there is unexpected array within filtered objects:

Results.vue?82a0:202 Uncaught (in promise) TypeError: Cannot read property 'vocabularyReferenceItem' of undefined
    at eval (Results.vue?82a0:202)
    at Array.filter (<anonymous>)
    at eval (Results.vue?82a0:201)

How can I avoid the error when do filter on other, non-array elements?

Here you can examine the data model, it's console.log'ed: https://lucid-villani-539a6f.netlify.com/results

Upvotes: 0

Views: 1769

Answers (2)

Tyler Roper
Tyler Roper

Reputation: 21672

If you're trying to look for "Abdomen" regardless of whether it's a single object or an array of those objects, you could use [].concat(repeatableGroupItem). This allows you to safely assume you're dealing with an array instead of handling each case individually.

From there you could use .some() to determine if "Abdomen" exists within any of the items.

// This array contains 4 objects... 
//   1: repeatableGroupItem as single object, containing "Abdomen"
//   2: repeatableGroupItem as array of objects, containing "Abdomen"
//   3: repeatableGroupItem as single object, without "Abdomen"
//   4: repeatableGroupItem as array of objects, without "Abdomen"
const returnedDocs = [{ repeatableGroup: { repeatableGroupItem: { vocabularyReference: { vocabularyReferenceItem: { formattedValue: { _text: "Abdomen" } } } } } }, { repeatableGroup: { repeatableGroupItem: [{ vocabularyReference: { vocabularyReferenceItem: { formattedValue: { _text: "Abdomen" } } } }, { vocabularyReference: { vocabularyReferenceItem: { formattedValue: { _text: "Abdomen" } } } } ] } }, { repeatableGroup: { repeatableGroupItem: { vocabularyReference: { vocabularyReferenceItem: { formattedValue: { _text: "Not Abdomen" } } } } } }, { repeatableGroup: { repeatableGroupItem: [{ vocabularyReference: { vocabularyReferenceItem: { formattedValue: { _text: "Not Abdomen" } } } }, { vocabularyReference: { vocabularyReferenceItem: { formattedValue: { _text: "Not Abdomen" } } } } ] } }];

const result = returnedDocs.filter(o => {
  const item = [].concat(o.repeatableGroup.repeatableGroupItem);
  return item.some(i => i.vocabularyReference.vocabularyReferenceItem.formattedValue._text === "Abdomen");
});

//Logs items 1 and 2
console.log(result);

Upvotes: 0

Barmar
Barmar

Reputation: 781310

If you just want to ignore the arrays, you can simply test whether repeatableGroup has a vocabularyReferences property.

let toFilterSix = returnedDocs.filter(
  o =>
  o.repeatableGroup.repeatableGroupItem.vocabularyReference &&
  o.repeatableGroup.repeatableGroupItem.vocabularyReference.vocabularyReferenceItem.formattedValue._text === "Abdomen"
);

If you want to search the array as well, you can use an if statement to search that when it's an array.

let toFilterSix = returnedDocs.filter(
  o => {
    if (Array.isArray(o.repeatableGroup.repeatableGroupItem)) {
      return o.repeatableGroup.repeatableGroupItem.some(el => el.vocabularyReference.vocabularyReferenceItem.formattedValue._text === "Abdomen");
    } else {
      return o.repeatableGroup.repeatableGroupItem.vocabularyReference.vocabularyReferenceItem.formattedValue._text === "Abdomen";
    }
  });

Upvotes: 1

Related Questions