get latest date for each day in an array of object? - javascript

i have array of object which are sorted based on date/time, I have to form an array of object with latest data from each date?. I'm getting the solution with for loop but I need to use es6 and above, please help me with a better and advanced solution.
var array = [
{
"id": 1,
"date": "2016-01-15T16:18:44.258843Z",
"status": "NEW",
"request": 4
},
{
"id": 2,
"date": "2016-01-15T18:18:44.258843Z",
"status": "NEW",
"request": 4
},
{
"id": 3,
"date": "2016-01-15T20:18:44.258843Z",
"status": "NEW",
"request": 4
},
{
"id": 4,
"date": "2016-01-19T16:18:44.258843Z",
"status": "STD",
"request": 4
},
{
"id": 6,
"date": "2016-01-23T17:18:44.258843Z",
"status": "FOR",
"request": 4
},
{
"id": 5,
"date": "2016-01-23T16:18:44.258843Z",
"status": "FOR",
"request": 4
}]
const list = filter(array, el => (el.date));
latestDate = list[0]?.date.slice(0, 10);
latestResponse.push(res[0]);
for (let i = array.length - 1; i > 0; i--) {
if (this.latestDate !== array[i].date.slice(0, 10)) {
latestDate = (array[i].date).slice(0, 10);
latestResponse.push(res[i]);
}
}
expected Output
var array = [
{
"id": 3,
"date": "2016-01-15T20:18:44.258843Z",
"status": "NEW",
"request": 4
},
{
"id": 4,
"date": "2016-01-19T16:18:44.258843Z",
"status": "STD",
"request": 4
},
{
"id": 5,
"date": "2016-01-23T17:18:44.258843Z",
"status": "FOR",
"request": 4
}]

Here is the code, use reduce method.
var array = [
{
"id": 1,
"date": "2016-01-15T16:18:44.258843Z",
"status": "NEW",
"request": 4
},
{
"id": 2,
"date": "2016-01-15T18:18:44.258843Z",
"status": "NEW",
"request": 4
},
{
"id": 3,
"date": "2016-01-15T20:18:44.258843Z",
"status": "NEW",
"request": 4
},
{
"id": 4,
"date": "2016-01-19T16:18:44.258843Z",
"status": "STD",
"request": 4
},
{
"id": 6,
"date": "2016-01-23T17:18:44.258843Z",
"status": "FOR",
"request": 4
},
{
"id": 5,
"date": "2016-01-23T16:18:44.258843Z",
"status": "FOR",
"request": 4
}];
console.clear();
let results = array.reduce((acc: any, cur: any) => {
let curDate = new Date(cur.date);
let curDateStr = curDate.getFullYear() + '-' + (curDate.getMonth() + 1) + '-' + curDate.getDate();
let existDateObj = acc.find(f => f.dStr === curDateStr);
if (existDateObj) {
let existDate = new Date(existDateObj.date);
if (curDate.getTime() > existDate.getTime()) {
acc = acc.filter(f => f.id !== existDateObj.id);
acc.push(Object.assign(cur, { dStr: curDateStr }));
}
} else {
acc.push(Object.assign(cur, { dStr: curDateStr }));
}
return acc;
}, []);
console.log(results);

You can try this. Sort, group, get
array.sort(function(a,b){
return new Date(a.date) - new Date(b.date);
});
var newArray=[];
result = array.reduce(function (r, a) {
r[a.status] = r[a.status] || [];
r[a.status].push(a);
return r;
}, Object.create(null));
for (const n in result) {
newArray.push(result[n].slice(-1))
}

Instead of using multiple array methods/loops, this can be done using a single for of loop as follows,
function getLatestDateInfo(array) {
let obj = {};
for (const item of array) {
var today = new Date(item.date);
var year = today.getFullYear();
var month = today.getMonth() + 1;
var day = today.getDate();
var mainDate = day + "-" + month + "-" + year;
obj = {
...obj,
[mainDate]: { ...item },
}
}
return Object.values(obj);
}
The above solution is based on the assumption that the array of objects are sorted based on date/time, as this is mentioned in the question.

const latestResponse = [];
const list = filter(res, el => (el.date));
let latestDate = moment(list[0]?.date).format("DD/MM/YYYY");
[...res].reverse().filter(el => {
if (latestDate !== moment(el.date).format("DD/MM/YYYY")) {
latestDate = moment(el.date).format("DD/MM/YYYY");
latestResponse.push(el);
}
})
used moment to format the date, and used filter to generate the new array

var array = [
{
"id": 1,
"date": "2016-01-15T16:18:44.258843Z",
"status": "NEW",
"request": 4
},
{
"id": 2,
"date": "2016-01-15T18:18:44.258843Z",
"status": "NEW",
"request": 4
},
{
"id": 3,
"date": "2016-01-15T20:18:44.258843Z",
"status": "NEW",
"request": 4
},
{
"id": 4,
"date": "2016-01-19T16:18:44.258843Z",
"status": "STD",
"request": 4
},
{
"id": 6,
"date": "2016-01-23T17:18:44.258843Z",
"status": "FOR",
"request": 4
},
{
"id": 5,
"date": "2016-01-23T16:18:44.258843Z",
"status": "FOR",
"request": 4
}];
const sortedLatestArray = array.sort((a, b) => {
if(a.date > b.date) {
return -1;
} else if (a.date === b.date){
return 0;
} else {
return 1;
}
}).filter((item, i, sortedArray) => {
if(i) {
const prevItem = sortedArray[i - 1];
const prevItemDate = prevItem.date.slice(0, 10);
const currentItemDate = item.date.slice(0, 10);
return currentItemDate !== prevItemDate;
}
return true;
}).reverse();
console.log(sortedLatestArray);
Sort array latest to oldest, and then remove duplicated date item by comparing former Item and current Item using filter method, finally reverse array to make result sorted as oldest to latest.

Use forEach and build an object with keys as date. If the same date exist, then replace with latest date-time.
const refine = (arr) => {
const res = {};
arr.forEach((item) => {
const date_str = item.date.split('T')[0];
res[date_str] ??= { ...item };
if (new Date(item.date) > new Date(res[date_str].date)) {
res[date_str].date = item.date;
}
});
return Object.values(res);
};
var array = [
{
id: 1,
date: "2016-01-15T16:18:44.258843Z",
status: "NEW",
request: 4,
},
{
id: 2,
date: "2016-01-15T18:18:44.258843Z",
status: "NEW",
request: 4,
},
{
id: 3,
date: "2016-01-15T20:18:44.258843Z",
status: "NEW",
request: 4,
},
{
id: 4,
date: "2016-01-19T16:18:44.258843Z",
status: "STD",
request: 4,
},
{
id: 6,
date: "2016-01-23T17:18:44.258843Z",
status: "FOR",
request: 4,
},
{
id: 5,
date: "2016-01-23T16:18:44.258843Z",
status: "FOR",
request: 4,
},
];
console.log(refine(array));

Related

How to Filter Nested Object Array Without affecting References in JavaScript

Just want to remove all the items other than 14 from the parentId: 1001 and add that item to another object.
I want to filter the array without affecting the source array.
var Data = [{
"id": 1001,
"text": "A",
"items": [
{ "id": 13, "text": "Thirteen" },
{ "id": 14, "text": "Fourteen" },
{ "id": 15, "text": "Fifteen", }
]
},
{
"id": 1002,
"text": "B",
"items": [
{ "id": 21, "text": "TwentyOne" },
{ "id": 22, "text": "TwentyTwo" },
{ "id": 23, "text": "TwentyThree", }
]
}
]
var childId = 14;
Data.items.filter((x) => {
return x.id != childId;
})
//this is affecting the source array (Data)
//after searching on internet found a solution
Data.items.filter((x) => {
return x.id childId;
}).map(function(x) {
return x
});
Your Data has no items property: it is an array, so you actually have Data[0].items, Data[1].items, ...
NB: it is common practice to use camelCase for such variable names, and reserve PascalCase for constructors/classes
Here is how you could do it:
const data = [{"id": 1001,"text": "A","items": [{ "id": 13, "text": "Thirteen" }, { "id": 14, "text": "Fourteen" }, { "id": 15, "text": "Fifteen", }]},{"id": 1002,"text": "B","items": [{ "id": 21, "text": "TwentyOne" }, { "id": 22, "text": "TwentyTwo" }, { "id": 23, "text": "TwentyThree", }]}]
const childId = 14;
const newData = data.map(obj => ({
...obj,
items: obj.items.filter(x => x.id != childId)
}));
console.log(newData);
As you want to filter out a few items from an array object and want to add those into another object.
You can also achieve this requirement by doing a deep copy of an original array with the help of structuredClone() API and then iterating it using Array#forEach method.
Live demo :
const data=[
{
"id":1001,
"text":"A",
"items":[
{
"id":13,
"text":"Thirteen"
},
{
"id":14,
"text":"Fourteen"
},
{
"id":15,
"text":"Fifteen",
}
]
},
{
"id":1002,
"text":"B",
"items":[
{
"id":21,
"text":"TwentyOne"
},
{
"id":22,
"text":"TwentyTwo"
},
{
"id":23,
"text":"TwentyThree",
}
]
}
];
const clone = structuredClone(data);
let remainingItems = [];
clone.forEach(obj => {
if (obj.id === 1001) {
remainingItems = obj.items.filter(({ id }) => id !== 14);
obj.items = obj.items.filter(({ id }) => id === 14);
} else {
obj.items = [...obj.items, ...remainingItems];
}
})
console.log('cloned data_____', clone);
console.log('source data_____', data);

Get object value based on conditions within nested array objects

I have an array of objects called orders:
const orders = [
{
"order_id": 47445,
"order_type": "Wholesale",
"items": [
{
"id": 9,
"department": "Womens",
"type": "Dress",
"quantity": 4,
"detail": {
"ID": 13363,
"On Sale": 1,
}
}
]
}
];
I need to get the quantity when both the order_type (Wholesale) and items.detail.ID (13363) match.
I have so far tried the following:
const result = orders.find(item => item.order_type == "Wholesale").items
.reduce((total, item) => {
if(item.detail.ID == 13363) {
return item.quantity;
}
}, 0);
Where result correctly returns 4
My issue, and I'm sure I am missing something very simple is that when I have multiple items in my orders array, it fails.
const orders = [
{
"order_id": 47445,
"order_type": "Wholesale",
"items": [
{
"id": 9,
"department": "Womens",
"type": "Dress",
"quantity": 4,
"detail": {
"ID": 13363,
"On Sale": 1,
}
},
{
"id": 56,
"department": "Womens",
"type": "Skirt",
"quantity": 12,
"detail": {
"ID": 76884,
"On Sale": 0,
}
},
{
"id": 89,
"department": "Mens",
"type": "Shirts",
"quantity": 20,
"detail": {
"ID": 98223,
"On Sale": 1,
}
}
]
}
];
The same
const result = orders.find(item => item.order_type == "Wholesale").items
.reduce((total, item) => {
if(item.detail.ID == 13363) {
return item.quantity;
}
}, 0);
returns undefined
Thank you
The find helper just returns the first match, so you need to use another helper like filter, like this:
const ID = 13363;
const result = orders
.filter((order) => order.order_type === 'Wholesale')
.reduce((acc, curr) => {
const items = curr.items.filter((item) => item.detail.ID === ID);
console.log(items);
// You can sum the matching items and then push them into the acc array
const quantity = items.reduce((sum, item) => (sum += item.quantity), 0);
acc.push(quantity);
return acc;
}, []);
This will return an array of matching quantities.
Not sure about the use case but here you go
const result = orders.find(item => item.order_type == "Wholesale").items
.reduce((total, item) => {
if (item.detail.ID == 13363) {
total += item.quantity;
}
return total
}, 0);
You can even create a function to make the search dynamic.
const orders = [
{
"order_id": 47445,
"order_type": "Wholesale",
"items": [
{
"id": 9,
"department": "Womens",
"type": "Dress",
"quantity": 4,
"detail": {
"ID": 13363,
"On Sale": 1,
}
},
{
"id": 56,
"department": "Womens",
"type": "Skirt",
"quantity": 12,
"detail": {
"ID": 76884,
"On Sale": 0,
}
},
{
"id": 89,
"department": "Mens",
"type": "Shirts",
"quantity": 20,
"detail": {
"ID": 98223,
"On Sale": 1,
}
}
]
}
];
findMyItem=( ID )=>{
var result = null ;
const result2 = orders.find(item => item.order_type == "Wholesale").items
.map(( item) => {
if(item.detail.ID == ID ) {
result = item.quantity;
}
}, 0);
return result ;
}
console.log( "result" ,findMyItem( 13363 ) )
console.log( "result" ,findMyItem( 98223) )
console.log( "result" ,findMyItem( 76884) )
You could use Array.find() on the orders array to find the correct order, searching for the first order that matches both the order_type and has an item matching the desired itemId (using Array.some()).
If this order exists, we can then find the corresponding item quantity using .find() again,
const orders = [ { "order_id": 47445, "order_type": "Wholesale", "items": [ { "id": 9, "department": "Womens", "type": "Dress", "quantity": 4, "detail": { "ID": 13363, "On Sale": 1, } }, { "id": 56, "department": "Womens", "type": "Skirt", "quantity": 12, "detail": { "ID": 76884, "On Sale": 0, } }, { "id": 89, "department": "Mens", "type": "Shirts", "quantity": 20, "detail": { "ID": 98223, "On Sale": 1, } } ] } ]
function findItemQuantity(orders, orderType, itemId) {
// Find the first order with the right order_type and containing the right item id
const order = orders.find(order => order.order_type = orderType && order.items.some(item => item.detail.ID === itemId));
if (!order) {
return null;
}
const item = order.items.find(item => item.detail.ID === itemId);
if (!item) {
return null;
}
return item.quantity;
}
console.log("Quantity found:", findItemQuantity(orders, 'Wholesale', 13363))
console.log("Quantity found:", findItemQuantity(orders, 'Wholesale', 76884))
const result = orders
.filter(order => order.order_type == "Wholesale")
.map(order => order.items.find(item => item.detail.ID == 13363))
.filter(item => item)
.reduce((total, { quantity }) => quantity + total, 0);
const orders = [{
"order_id": 47445,
"order_type": "Wholesale",
"items": [{
"id": 9,
"department": "Womens",
"type": "Dress",
"quantity": 4,
"detail": {
"ID": 13363,
"On Sale": 1,
}
}]
},
{
"order_id": 47445,
"order_type": "Whole",
"items": [{
"id": 9,
"department": "Womens",
"type": "Dress",
"quantity": 4,
"detail": {
"ID": 13363,
"On Sale": 1,
}
}]
}
]
const result = orders.reduce(v => {
return v.items.map(a => {
if (v.order_type == 'Wholesale' && a.detail.ID == 13363) {
return v
}
})
})
console.log(result)
const orders = [{
"order_id": 47445,
"order_type": "Wholesale",
"items": [{
"id": 9,
"department": "Womens",
"type": "Dress",
"quantity": 4,
"detail": {
"ID": 13363,
"On Sale": 1,
}
}]
}];
var result = null;
const result2 = orders.find(item => item.order_type == "Wholesale").items
.map((item) => {
if (item.detail.ID == 98223) {
result = item.quantity;
}
}, 0);
console.log("result", result)

Comparing an array with another array plus adding a counter

So I'm reformatting my data and I noticed that my data isn't quite getting restructured the way I want it to. I noticed that my results come back as
[
{
"name": "sites",
"parent": null,
"count": 3
},
{
"name": "group1",
"parent": "sites",
"count": 3
},
{
"name": "bk",
"parent": "group1",
"count": 3
},
{
"name": "sitepages",
"parent": "bk",
"count": 1
},
{
"name": "home.aspx",
"parent": "sitepages",
"count": 1
}
]
It isn't grabbing my "not matches". I've spent so much time looking it over and I'm coming to a blank. It should be
[
{
"name": "sites",
"parent": null,
"count": 3
},
{
"name": "group1",
"parent": "sites",
"count": 3
},
{
"name": "bk",
"parent": "group1",
"count": 3
},
{
"name": "sitepages",
"parent": "bk",
"count": 1
},
{
"name": "home.aspx",
"parent": "sitepages",
"count": 1
},
{
"name": "tester",
"parent": "bk",
"count": 1
},
{
"name": "tester",
"parent": "home.aspx",
"count": 1
},
{
"name": "_layouts",
"parent": "bk",
"count": 1
},
{
"name": "15",
"parent": "_layouts",
"count": 1
},
{
"name": "upload.aspx",
"parent": "15",
"count": 1
},
]
I believe something is missing in my loop.
var testArr = [
{
Author: { Title: "Mitchell" },
BrowserType: "FireFox",
Created: "2017-04-25T16:39:40Z",
pathname: "sites/group1/bk/sitepages/home.aspx"
},
{
Author: { Title: "Pierre" },
BrowserType: "Opera",
Created: "2017-04-25T16:39:40Z",
pathname: "sites/group1/bk/tester/home.aspx"
},
{
Author: { Title: "Mizell" },
BrowserType: "IE",
Created: "2017-04-25T16:47:02Z",
pathname: "sites/group1/bk/_layouts/15/upload.aspx"
}
];
function reduceData(data) {
var root = null;
var newArr = null;
var itemContainer = [];
var masterArr = [];
var filteredArr = [];
data.forEach(function (props, idx) {
//check the last character of the pathname is "/" and removes it
if (props.pathname.charAt(props.pathname.length - 1) === "/") {
props.pathname = props.pathname.substring(0, props.pathname.length - 1);
}
//lowercase the pathname + split into strings
props.pathname = props.pathname.toLowerCase().split("/");
//format the pathname
var lastItem = "";
newArr = props.pathname.reduce(function (acc, props, index) {
if (acc.length === 0) {
acc.push({ name: props, parent: null, count: 1 });
lastItem = props;
} else {
acc.push({ name: props, parent: lastItem, count: 1 });
lastItem = props;
}
return acc;
}, []);
//The first iteration
if (idx === 0) {
itemContainer = newArr;
} else {
for (var i = 0; i < itemContainer.length; i++) {
// Loop for newArr
for (var j = 0; j < newArr.length; j++) {
//compare the element of each and every element from both of the arrays
//console.log(masterArr[i], newArr[j]);
if (
itemContainer[i].name === newArr[j].name &&
itemContainer[i].parent === newArr[j].parent
) {
//Match
masterArr[i] = {
name: itemContainer[i].name,
parent: itemContainer[i].parent,
count: itemContainer[i].count++
};
} else {
//Doesn't Match
masterArr[i] = {
name: itemContainer[i].name,
parent: itemContainer[i].parent,
count: itemContainer[i].count
};
}
}
}
}
});
console.log(masterArr)
}
reduceData(testArr)
ok.. I revamp your code a little..
delete the if else after the //The first iteration, and use this instead..
newArr.forEach((newEl) => {
const matchIdx = masterArr.findIndex((masterEl) => masterEl.name === newEl.name && masterEl.parent === newEl.parent);
if(matchIdx < 0){
masterArr.push(newEl);
}
else {
masterArr[matchIdx].count = masterArr[matchIdx].count + 1;
}
});

How to calculate sum of count of array elements of multiple arrays by order and limit?

I have 3 arrays of 3 different types. Each array contains the count of an id (which might be duplicate like arrayOfB).
Each id has a limit value of count property is 10 (the count includes different types. Ex: if unique1 has 10 counts in type A, when process type B for unique1, it will be not processed).
const arrayOfA = [
{
"type": "A", "count": 10, "id": "UID1"
},
{
"type": "A", "count": 20, "id": "UID2"
},
{
"type": "A", "count": 1, "id": "UID4"
},
];
const arrayOfB = [
{
"type": "B", "count": 5, "id": "UID1"
},
{
"type": "B", "count": 5, "id": "UID3"
},
];
const arrayOfC = [
{
"type": "C", "count": 6, "id": "UID1"
},
{
"type": "C", "count": 6, "id": "UID4"
},
{
"type": "C", "count": 3, "id": "UID2"
},
{
"type": "C", "count": 3, "id": "UID3"
},
]
The output will be like:
Map {
'UID1|A' => 10,
'UID2|A' => 10,
'UID4|A' => 1,
'UID3|B' => 5,
'UID4|C' => 6 }
I used a set to hold id, which already has the maximum count and map to hold the output.
const maxed = new Set();
const elements = new Map();
arrayOfA.forEach(element => {
if (element.count > 10) {
maxed.add(`${element.id}`);
elements.set(`${element.id}|${element.type}`, 10);
console.log(elements)
return;
}
if (elements.has(`${element.id}|${element.type}`)) {
const newCount = elements.get(`${element.id}|${element.type}`) + element.count;
newCount > 10 ? elements.set(`${element.id}|${element.type}`, 10) : elements.set(`${element.id}|${element.type}`, newCount);
console.log(elements)
return;
}
elements.set(`${element.id}|${element.type}`, element.count);
});
arrayOfB.forEach(element => {
if (maxed.has(`${element.id}`)) {
console.log(elements)
return;
}
const countOfA = elements.has(`${element.id}|A`) ? elements.get(`${element.id}|A`) : 0;
let newCount = countOfA + element.count;
if (elements.has(`${element.id}|${element.type}`)) {
newCount = newCount + element.get(`${element.id}|${element.type}`);
}
if (newCount > 10) {
maxed.add(`${element.id}`);
if ((10 - countOfA) > 0) elements.set(`${element.id}|${element.type}`, 10 - countOfA);
console.log(elements)
return;
}
elements.set(`${element.id}|${element.type}`, element.count);
})
arrayOfC.forEach(element => {
if (maxed.has(`${element.id}`)) {
console.log(elements)
return;
}
const countOfA = elements.has(`${element.id}|A`) ? elements.get(`${element.id}|A`) : 0
const countOfB = elements.has(`${element.id}|C`) ? elements.get(`${element.id}|C`) : 0
let newCount = countOfA + countOfB + element.count;
if (elements.has(`${element.id}|${element.type}`)) {
newCount = newCount + element.get(`${element.id}|${element.type}`);
}
if (newCount > 10) {
maxed.add(`${element.id}`);
if ((10 - countOfA - countOfB) > 0); elements.set(`${element.id}|${element.type}`, 10 - countOfA - countOfB);
console.log(elements)
return;
}
elements.set(`${element.id}|${element.type}`, element.count);
})
I want to ask about another faster implementation if any. I estimated my big O will be O(n) (n is the total length of 3 arrays). If elements of arrays do not contain the same id.
Edit:
Big thanks to you all, but seems like there's one edge case. The answers couldn't handle
var arrayOfA = [
{
"type": "A", "count": 10, "id": "UID1"
},
{
"type": "A", "count": 20, "id": "UID2"
},
{
"type": "A", "count": 1, "id": "UID4"
},
];
const arrayOfB = [
{
"type": "B", "count": 5, "id": "UID1"
},
{
"type": "B", "count": 5, "id": "UID3"
},
{
"type": "B", "count": 1, "id": "UID3"
},
];
var arrayOfC = [
{
"type": "C", "count": 6, "id": "UID1"
},
{
"type": "C", "count": 6, "id": "UID4"
},
{
"type": "C", "count": 3, "id": "UID2"
},
{
"type": "C", "count": 3, "id": "UID3"
},
]
In arrayOfB, I have the UID3 occurs twice, so your answers doesn't seem to work on that case.
Instead of a Set for a maxed id, you could sum the count for every id and use it for all following arrays.
const
getKey = (...a) => a.join('|'),
rawData = [{ type: "A", count: 10, id: "UID1" }, { type: "A", count: 20, id: "UID2" }, { type: "A", count: 1, id: "UID4" }],
rawData3 = [{ type: "B", count: 5, id: "UID1" }, { type: "B", count: 5, id: "UID3" }],
rawData2 = [{ type: "C", count: 6, id: "UID1" }, { type: "C", count: 6, id: "UID4" }, { type: "C", count: 3, id: "UID2" }, { type: "C", count: 3, id: "UID3" }],
elements = new Map,
sums = new Map;
[rawData, rawData3, rawData2].forEach(a => a.forEach(({ type, count, id }) => {
var sum = sums.get(id) || 0,
key = getKey(id, type);
sums.set(id, sum + count);
if (sum >= 10) return;
if (sum + count > 10) {
if (10 - sum > 0) elements.set(key, 10 - sum);
return;
}
elements.set(key, count);
}));
[...elements].map(a => console.log(a.join(': ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Based on the assumption that you have missed to include "B" in your expected results set, two nested loops can provide the manipulation and filtering you want.
function getIdSummary(arrays) {
const maxValue = 10;
//Array of objects which we later conver to a map
//The aim is ease of indexing during the iterations
var summary = []
//A heler to find if a maxed uid is found in the summary
function isMaxed(uid) {
return summary.some(item => {
return item.uid === uid && item.count >= maxValue;
})
}
//Iterate all the arrays
arrays.forEach(anInputArray => {
//Iterate each array
anInputArray.forEach(item => {
if (!isMaxed(item.id)) {
summary.push({uid: item.id, type: item.type, count: item.count > maxValue ? 10 : item.count})
}
})
})
return new Map(summary.map(obj => {
return [obj.uid + '|' + obj.type, obj.count]
}))
}
var arrayOfA = [
{
"type": "A", "count": 10, "id": "UID1"
},
{
"type": "A", "count": 20, "id": "UID2"
},
{
"type": "A", "count": 1, "id": "UID4"
},
];
const arrayOfB = [
{
"type": "B", "count": 5, "id": "UID1"
},
{
"type": "B", "count": 5, "id": "UID3"
},
];
var arrayOfC = [
{
"type": "C", "count": 6, "id": "UID1"
},
{
"type": "C", "count": 6, "id": "UID4"
},
{
"type": "C", "count": 3, "id": "UID2"
},
{
"type": "C", "count": 3, "id": "UID3"
},
]
var m = getIdSummary([arrayOfA, arrayOfB, arrayOfC]);
console.log(Array.from(m));

How to do a foreach for an array with values that have to match specific key and the same value from another array

I have two arrays with data from my database:
Cases array and photo's array from api:
{
"cases": [{
"id": 3,
"photo_id": 14
}, {
"id": 2,
"photo_id": 0
}, {
"id": 1,
"photo_id": 13
}],
"photos": [{
"id": 6,
"file": "\/images\/1556196076cache_f50f03558d201b8eb2a9af90f0838cee.png"
}, {
"id": 11,
"file": "\/images\/1556198414cache_702c216fa5a4d75d74db237ddf97b012.png"
}, {
"id": 12,
"file": "\/images\/1556198946cache_702c216fa5a4d75d74db237ddf97b012.png"
}, {
"id": 13,
"file": "\/images\/1556726055dewekkpot.nl_short.jpg"
}, {
"id": 14,
"file": "\/images\/1556791722dewekkpot.nl_short.jpg"
}]
}
Now if any photo_id from the cases array matches any id from the photos array with the same value, i have to extract the file key from that specific index with the matching id. And push them as a new key value pair to the cases array at the correct index.
What i now have is the following:
this.state = {
cases: [],
photos: [],
};
getCases() {
axios
.get('/cases/api')
.then(response => {
this.setState({
cases: response.data.cases,
photos: response.data.photos,
});
console.log(this.state.cases);
})
}
addPhotos() {
var photoIds = this.state.photos.map(function (player) {
return player.id;
});
var casesIds = this.state.cases.map(function (player) {
return player.photo_id;
});
casesIds = casesIds.filter(function (item) {
return photoIds.includes(item);
});
console.log(casesIds);
}
The output of this are the values that exists in the cases array from the photos array.
so [13, 14].
what should i do next?
Thanks in advance!
You can filter the objects as below snippet and use it to render your view.
const obj = {
"cases": [{
"id": 3,
"photo_id": 14
}, {
"id": 2,
"photo_id": 0
}, {
"id": 1,
"photo_id": 13
}],
"photos": [{
"id": 6,
"file": "\/images\/1556196076cache_f50f03558d201b8eb2a9af90f0838cee.png"
}, {
"id": 11,
"file": "\/images\/1556198414cache_702c216fa5a4d75d74db237ddf97b012.png"
}, {
"id": 12,
"file": "\/images\/1556198946cache_702c216fa5a4d75d74db237ddf97b012.png"
}, {
"id": 13,
"file": "\/images\/1556726055dewekkpot.nl_short.jpg"
}, {
"id": 14,
"file": "\/images\/1556791722dewekkpot.nl_short.jpg"
}]
};
const photoIds = obj.cases.reduce((acc, val) => {
acc[val.photo_id] = val;
return acc;
}, {});
const res = obj.photos.filter(val => photoIds[val.id]);
console.log(res)
Normalise your data. Convert your photos array to an object with photo_id as keys, for easy access.
You could do something like the following:
addPhotos() {
var photosMap = this.state.photos.reduce(function (acc, each) {
acc[each.id] = each; // or you could just save the corresponding filename
return acc;
}, {});
var photoFiles = this.state.cases.reduce(function (acc, each) { // you could alternatively use Array.filter too.
if (photosMap[each.photo_id]) {
acc.push(photosMap[each.photo_id]);
}
return acc;
}, []);
console.log(photoFiles);
}
You can use Array.map() and Array.find() like this:
const newCases = this.state.cases.map(({ photo_id, ...rest }) => {
const obj = { ...rest };
this.state.photos.find(ph => {
if(ph.id === photo_id) {
obj.file = ph.file;
return true;
}
});
return obj;
});
Live example:
const data = {
"cases": [{
"id": 3,
"photo_id": 14
}, {
"id": 2,
"photo_id": 0
}, {
"id": 1,
"photo_id": 13
}],
"photos": [{
"id": 6,
"file": "\/images\/1556196076cache_f50f03558d201b8eb2a9af90f0838cee.png"
}, {
"id": 11,
"file": "\/images\/1556198414cache_702c216fa5a4d75d74db237ddf97b012.png"
}, {
"id": 12,
"file": "\/images\/1556198946cache_702c216fa5a4d75d74db237ddf97b012.png"
}, {
"id": 13,
"file": "\/images\/1556726055dewekkpot.nl_short.jpg"
}, {
"id": 14,
"file": "\/images\/1556791722dewekkpot.nl_short.jpg"
}]
};
const newCases = data.cases.map(({ photo_id, ...rest }) => {
const obj = { ...rest };
data.photos.find(ph => {
if(ph.id === photo_id) {
obj.file = ph.file;
return true;
}
});
return obj;
});
console.log(newCases);
function addPhotos(cases, photos){
return cases.map(function (currentCase) {
const foundPhoto = photos.find(function(currentPhoto){
return currentPhoto.id === currentCase.photo_id;
});
currentCase.photo_path = foundPhoto? foundPhoto.file : "/images/blank_image.jpg";
return currentCase;
});
};
console.log(addPhotos(this.state.cases, this.state.photos));
//Output: [{"id":3,"photo_id":14,"photo_path":"/images/1556791722dewekkpot.nl_short.jpg"},{"id":2,"photo_id":0,"photo_path":"images/blank_image.jpg"},{"id":1,"photo_id":13,"photo_path":"/images/1556726055dewekkpot.nl_short.jpg"}]

Categories