Micheal J. Roberts
Micheal J. Roberts

Reputation: 4170

Filtering an array of objects inside of an array of objects?

I have the following data structure:

[
    {
        "performanceDatetime": "2020-01-28T08:00:00Z",
        "waivers": [
            {
                "ticketId": "66288",
            },
        ]
    },
    {
        "performanceDatetime": "2020-01-28T08:30:00Z",
        "waivers": [
            {
                "ticketId": "63152",
            },
            {
                "ticketId": "66113",
            }
        ]
    },
    {
        "performanceDatetime": "2020-01-28T09:00:00Z",
        "waivers": [
            {
                "ticketId": "62667",
            },
        ]
    }
]

i.e., a list of objects. Inside these objects, there is another list: waivers. My question is, how would I filter the list waivers inside the list of objects, such that, if I filtered by, e.g., a ticketID of 63152, I'd receive the following returned:

[
    {
        "performanceDatetime": "2020-01-28T08:30:00Z",
        "waivers": [
            {
                "ticketId": "63152",
            }
        ]
    }
]

Assuming the original data structure is stored as this.activeSurfersWaivers, I have tried the following:

const todaysWaivers = this.activeSurfersWaivers.filter((surfersWaivers) => {
    surfersWaivers.waivers.filter((surferWaiver) => {
         return (surferWaiver.ticketId.indexOf(this.searchedTicketID) >= 0);
    });
});

Which returns an empty array for a value of this.searchedTicketID of 63152. Any pro-tips on filtering this awkward data structure would be greatly appreciated!

Upvotes: 1

Views: 114

Answers (6)

Scott Sauyet
Scott Sauyet

Reputation: 50787

Although these techniques are very similar to those in the answer by connexo, I find it cleaner to make a reusable function. This is what I came up with:

const matchingPerformances = (data, id) => data
  .filter (({waivers}) => waivers .some (({ticketId}) => ticketId == id))
  .reduce ((a, {waivers, ... r}) => [
    ... a, 
    {... r, waivers: waivers .filter (({ticketId}) => ticketId == id)}
  ], []) 

const data = [{performanceDatetime: "2020-01-28T08: 00: 00Z", waivers: [{ticketId: "66288"}]}, {performanceDatetime: "2020-01-28T08: 30: 00Z", waivers: [{ticketId: "63152"}, {ticketId: "66113"}]}, {performanceDatetime: "2020-01-28T09: 00: 00Z", waivers: [{ticketId: "62667"}]}]

console .log (matchingPerformances (data, "63152"))

If I wanted to clean up some duplication, I might add a helper function:

const ticketMatch = (id) => ({ticketId}) => ticketId == id

const matchingPerformances = (data, id) => data
  .filter (({waivers}) => waivers .some (ticketMatch (id)))
  .reduce ((a, {waivers, ... r}) => [
    ... a, 
    {... r, waivers: waivers .filter (ticketMatch (id))}
  ], []) 

While this could be done in a single reduce call, I think that would end up being much harder code to understand.

Upvotes: 0

100PercentVirus
100PercentVirus

Reputation: 17

I hope this solution is what you are looking for. It takes care of instances where there are multiple waivers array entries.

var dataStructure = 
[
    {
        "performanceDatetime": "2020-01-28T08:00:00Z",
        "waivers": [
            {
                "ticketId": "66288",
            },
        ]
    },
    {
        "performanceDatetime": "2020-01-28T08:30:00Z",
        "waivers": [
            {
                "ticketId": "63152",
            },
            {
                "ticketId": "66113",
            }
        ]
    },
    {
        "performanceDatetime": "2020-01-28T09:00:00Z",
        "waivers": [
            {
                "ticketId": "62667",
            },
        ]
    }
]; 

function filterDataStructureByWaiverTicketId(ticketId) 
{
    return dataStructure.filter(function (value, index, array) 
    { 
        //find index in the "waivers" array where ticketId occurs 
        var waiverIndex = value.waivers.reduce(function(a, e, i)
        {  
            if (e.ticketId === ticketId)
            {
                a.push(i);
            }  
            return a; 
        }, []); 
        if(waiverIndex.length > 0)//if a match exists 
        {   //remove everything in the "waivers" array that does not match 
            var newWaivers = value.waivers.filter(function (value, index, array)
            {  
                return value.ticketId === ticketId;
            });
            value.waivers = newWaivers;//replace the old waivers array with the new one that matches
            return value.waivers[0].ticketId === ticketId;//tadaa... 
        }  
    });
}

Usage example:

Example 1: 
var newdatastructure = filterDataStructureByWaiverTicketId("66113");/*
newdatastructure[0].performanceDatetime //returns "2020-01-28T08:30:00Z"
newdatastructure[0].waivers[0].ticketId //returns "66113"
newdatastructure //returns   
[
    {
        "performanceDatetime": "2020-01-28T08:30:00Z",
        "waivers": [
            {
                "ticketId": "66113",
            }
        ]
    }
]*/

Example 2: 
var newdatastructure = filterDataStructureByWaiverTicketId("63152");/*
newdatastructure[0].performanceDatetime //returns "2020-01-28T08:30:00Z"
newdatastructure[0].waivers[0].ticketId //returns "63152"
newdatastructure // returns   
[
    {
        "performanceDatetime": "2020-01-28T08:30:00Z",
        "waivers": [
            {
                "ticketId": "63152",
            }
        ]
    }
]*/

Example 3: 
var newdatastructure = filterDataStructureByWaiverTicketId("66288");/*
newdatastructure[0].performanceDatetime //returns "2020-01-28T08:00:00Z"
newdatastructure[0].waivers[0].ticketId //returns "66288"
newdatastructure //returns   
[
    {
        "performanceDatetime": "2020-01-28T08:00:00Z",
        "waivers": [
            {
                "ticketId": "66288",
            }
        ]
    }
]*/

Upvotes: 0

Siva Kondapi Venkata
Siva Kondapi Venkata

Reputation: 11001

UPDATE: Adding multiple ways to do.

  1. Using reduce method. (find_item method)
  2. Using for of loop. (find_item2 method)

const find_item = (arr, searchId) =>
  arr.reduce((acc, curr) => {
    const waivers = curr.waivers.filter(waiver => waiver.ticketId === searchId);
    return waivers.length > 0 ? [{ ...acc, ...curr, waivers }] : [...acc];
  }, []);


const find_item2 = (arr, searchId) => {
  for (let curr of arr) {
    const waivers = curr.waivers.filter(waiver => waiver.ticketId === searchId);
    if (waivers.length > 0) {
      return [{ ...curr, waivers }];
    }
  }
  return [];
};

const arr = [
  {
    performanceDatetime: "2020-01-28T08:00:00Z",
    waivers: [
      {
        ticketId: "66288"
      }
    ]
  },
  {
    performanceDatetime: "2020-01-28T08:30:00Z",
    waivers: [
      {
        ticketId: "63152"
      },
      {
        ticketId: "66113"
      }
    ]
  },
  {
    performanceDatetime: "2020-01-28T09:00:00Z",
    waivers: [
      {
        ticketId: "62667"
      }
    ]
  }
];
const searchId = "66113";

console.log(find_item(arr, searchId));
console.log(find_item2(arr, searchId));

Upvotes: -1

connexo
connexo

Reputation: 56754

This is what I would do if I had to rush it:

const data = [{
    "performanceDatetime": "2020-01-28T08:00:00Z",
    "waivers": [{
      "ticketId": "66288",
    }, ]
  },
  {
    "performanceDatetime": "2020-01-28T08:30:00Z",
    "waivers": [{
        "ticketId": "63152",
      },
      {
        "ticketId": "66113",
      }
    ]
  },
  {
    "performanceDatetime": "2020-01-28T09:00:00Z",
    "waivers": [{
      "ticketId": "62667",
    }, ]
  }
]

const idToFind = "63152";

const matchingEntries = data.filter(entry => entry.waivers.some(el => el.ticketId === idToFind));
matchingEntries.forEach(entry => entry.waivers = entry.waivers.filter(el => el.ticketId === idToFind));

console.log(matchingEntries);

This returns

[
  {
    "performanceDatetime": "2020-01-28T08:30:00Z",
    "waivers": [
      {
        "ticketId": "63152"
      }
    ]
  }
]

Upvotes: 2

Tim VN
Tim VN

Reputation: 1193

You are actually very close. You'll want to check if the second filter yields any results:

data = [
  {
    "performanceDatetime": "2020-01-28T08:00:00Z",
    "waivers": [
      {
        "ticketId": "66288",
      },
    ]
  },
  {
    "performanceDatetime": "2020-01-28T08:30:00Z",
    "waivers": [
      {
        "ticketId": "63152",
      },
      {
        "ticketId": "66113",
      }
    ]
  },
  {
    "performanceDatetime": "2020-01-28T09:00:00Z",
    "waivers": [
      {
        "ticketId": "62667",
      },
    ]
  }
];

const filter = ticket => {
  return data.filter(entry => {
    return entry.waivers.some(waiver => waiver.ticketId === ticket)
  }).map(entry => {
    entry.waivers = entry.waivers.filter(waiver => waiver.ticketId === ticket);
    return entry;
  });
};

console.log(filter("63152"));

Upvotes: 1

Vijay Joshi
Vijay Joshi

Reputation: 959

Here is how you do it:

https://codepen.io/v08i/pen/KKwYrRp

<div id="test1">
</div>
<div id="test2">
</div>

let arr = [
    {
        "performanceDatetime": "2020-01-28T08:00:00Z",
        "waivers": [
            {
                "ticketId": "66288",
            },
        ]
    },
    {
        "performanceDatetime": "2020-01-28T08:30:00Z",
        "waivers": [
            {
                "ticketId": "63152",
            },
            {
                "ticketId": "66113",
            }
        ]
    },
    {
        "performanceDatetime": "2020-01-28T09:00:00Z",
        "waivers": [
            {
                "ticketId": "62667",
            },
        ]
    }
]

function findItem(id) {
    return arr.find((item) => {
        return item.waivers.some((waiver) => { return waiver.ticketId == id});
    });
}

document.getElementById('test1').innerHTML = JSON.stringify(findItem('63152')); 

document.getElementById('test2').innerHTML = JSON.stringify(findItem('62667')); 

console.log(findItem('63152'));
console.log(findItem('62667'));

Upvotes: 1

Related Questions