-1

I have an array of products and an array of products that a user has access to. They share a common ID. I want to filter the array of products to only return those that the user has access to.

All products (products)

[{
  "productName": "My Product"
   "p_id": "1"
},...
]

My available products (myProducts)

[
  {
    "i_items": "[{\"act\":\"new\",\"app\":\"nexus\",\"type\":\"package\",\"cost\":\"0.00\",\"tax\":null,\"quantity\":1,\"itemName\":\"My Product\",\"itemID\":1,\"physical\":false,\"methods\":\"*\",\"cfields\":[],\"extra\":null,\"renew_term\":1,\"renew_units\":\"m\",\"renew_cost\":\"100.00\",\"grace_period\":86400}]"
  },...
]

Edit:

The below solution is returning []

// Extract available IDs into a Set:
const availableIds = new Set(this.myProducts.flatMap(({i_items}) => 
    JSON.parse(i_items).map(item => ""+item.itemID))
);
console.log(availableIds); //Set(1) {"3"}
// Use the Set to filter the products:
console.log(availableIds.has("3")); //true
const filtered = this.products.filter(({p_id}) => availableIds.has(p_id));
console.log(filtered); // []

Final edit: thanks to everyone who helped. This last issue was caused by not casting the id to string. Once I changed availableIds.has(p_id) -> availableIds.has(""+p_id) it worked.

timelfelt
  • 680
  • 1
  • 11
  • 26
  • 2
    `i_items` is not an array, it is a JSON string, so you'll need to decode it at first. Then `map()` it by comparing `p_id` and `itemID`. – Kévin Bibollet Apr 25 '19 at 09:20
  • How to compare to all p_id's in the product array? – timelfelt Apr 25 '19 at 09:29
  • @timelf123, I think iArcadia just gave the right direction for that? Have you tried? What exactly is the problem you bump into while trying? Can you provide the code, and maybe the error message you get? – trincot Apr 25 '19 at 09:31
  • @trincot I was hitting a wall with a generic TS error when trying to use flatMap, sorry for being unclear. I've edited my original post with clarification – timelfelt Apr 25 '19 at 22:34

2 Answers2

4

You can use map and JSON.parse to extract the itemID values from the second data set, and turn those into a Set. Then apply a filter on the product data using that set:

// Sample data
const allProducts = [{"productName": "My Product","p_id": "1"},{"productName": "My unused Product","p_id": "4"},{"productName": "My Other Product","p_id": "5"},{"productName": "My unused Product 2","p_id": "6"},{"productName": "My luxury Product","p_id": "9"},{"productName": "My lucky Product","p_id": "13"}];
const available = [{"i_items": "[{\"itemID\":1},{\"itemID\":13}]"},{"i_items": "[{\"itemID\":5},{\"itemID\":9}]"}];

// Extract available IDs into a Set:
const availableIds = new Set(available.flatMap(({i_items}) => 
    JSON.parse(i_items).map(item => ""+item.itemID))
);
// Use the Set to filter the products:
const filtered = allProducts.filter(({p_id}) => availableIds.has(p_id));
console.log(filtered);
trincot
  • 317,000
  • 35
  • 244
  • 286
  • Thanks. This may seem silly but I am attempting to learn Typescript and hit the following roadblock on Angular 7 `Property 'flatMap' does not exist on type '[]'.ts`. Any thoughts? Done some googling but haven't found a fix yet – timelfelt Apr 25 '19 at 12:29
  • 1
    @timelf123 you need to update your tsconfig to get that feature: https://stackoverflow.com/questions/53556409/typescript-flatmap-flat-flatten-doesnt-exist-on-type-any – OliverRadini Apr 25 '19 at 12:44
  • Thank you, that solved it for the build! Next to solve it for the editor, VSCode. I am still having issues with the original question - see edited post – timelfelt Apr 25 '19 at 22:32
1

As others have said, this is a case of parsing the available items, and then checking to see if the relevant id is present:

const a = [
  {
    "productName": "My Product",
    "p_id": "1"
  },
  {
    "productName": "My Other Product",
    "p_id": "2"
  }
]


const availableItems = [
  {
    "i_items": "[{\"act\":\"new\",\"app\":\"nexus\",\"type\":\"package\",\"cost\":\"0.00\",\"tax\":null,\"quantity\":1,\"itemName\":\"My Product\",\"itemID\":1,\"physical\":false,\"methods\":\"*\",\"cfields\":[],\"extra\":null,\"renew_term\":1,\"renew_units\":\"m\",\"renew_cost\":\"100.00\",\"grace_period\":86400}]"
  },
];

const path = k => x => x[k];

const parseAvailable = item => JSON.parse(item['i_items']);

const stringify = x => `${x}`;
const getItemIdAsString = x => stringify(path('itemID')(x))

const availabilityChecker = available => product => parseAvailable(available)
  .map(getItemIdAsString)
  .indexOf(product['p_id']) > -1;

const isProductAvailable = availabilityChecker(availableItems[0]);

const result = isProductAvailable(a[0])
const resultTwo = isProductAvailable(a[1])

console.dir(result)
console.dir(resultTwo)
OliverRadini
  • 6,238
  • 1
  • 21
  • 46