Merging array items with null values considered - javascript

I have an array with data from different tables (at least 9 tables).I want to iterate through the array and kind of merge them in a way that the first item is taken from all arrays, then second and so on.
I'll better explain now with an example below.
So suppose I have an input array like the below :
var arrData = [{
"Id": 1,
"Name": 'Ken',
"Age": '',
"Hobbies": [{
'HobbyId': 1,
'HobbyName': 'Swimming'
}, {
'HobbyId': 2,
'HobbyName': 'Reading'
}],
"Skills": [{
'SkillId': 1,
'SkillName': 'PHP'
}, {
'SkillId': 2,
'SkillName': 'MySQL'
}],
"Language": [{
'LangId': 2,
'LangName': 'English'
}, {
'LangId': 3,
'LangName': 'Chinese'
}]
},
{
"Id": 2,
"Name": 'Mike',
"Age": '20',
"Hobbies": [],
"Skills": [],
"Language": []
},
{
"Id": 3,
"Name": 'Charlie',
"Age": '25',
"Hobbies": [{
'HobbyId': 5,
'HobbyName': 'Dance'
}, {
'HobbyId': 6,
'HobbyName': ''
}, {
'HobbyId': 7,
'HobbyName': 'Writing'
}],
"Skills": [],
"Language": [{
'LangId': 7,
'LangName': 'English'
}]
}
];
console.log(arrData);
My resulting array should be something as below :
[
[1,"Ken",'',1,'Swimming',1,'PHP',2,'English'],
[1,"Ken",'',2,'Reading',2,'MySQL',3,'Chinese'],
[2,"Mike",'20','','','','','',''],
[3,"Charlie",'25','5','Dance','','',7,'English'],
[3,"Charlie",'25','6','','','','',''],
[3,"Charlie",'25','7','Writing','','','',''],
]
Here you may notice that the loop for an item iterates for the maximum number of times found in array for that item.
So for the 3rd item with Id = 3 and Name = 'Charlie' the loop iterates for 3 times as there are 3 (maximum) item in Hobbies array.
The is just a sample array and in reality I will have 9 arrays and my code should be very dynamic to handle it.
I have achieved 90% of the output but I am only stuck where I should pass empty values for the items not found in the array.
For example in the sample above Mike has no items for Hobbies,Skills or Language, in that case I still have to pass empty values.
Or if you see Charlie has 3 Hobbies, no skills and 1 Language, my array should have 3 items but as the Skills is empty is should have empty values for them and for the second and third item for charlie it should have empty values for Language.
I hope this makes sense.
I have tried some code as below and I'll explain at the bottom.
$(function() {
// Handler for .ready() called.
var finalData = [],
arr = [],
arrHeader = [],
cnt = 0,
generateMaxRows = 0;
//finalData.push({"Id":"","Name":'',"Age" : '','HobbyId':'Hobbies','HobbyName':'', 'SkillId':'Skills','SkillName':'','LangId':'Language','LangName':''});
var arrHeader = [{
"Id": "Id",
"Name": 'Name',
"Age": 'Age',
"Hobbies": [{
'HobbyId': 'HobbyId',
'HobbyName': 'HobbyName'
}],
"Skills": [{
'SkillId': 'SkillId',
'SkillName': 'SkillName'
}],
"Language": [{
'LangId': 'LangId',
'LangName': 'LangName'
}]
}];
var arrData = [{
"Id": 1,
"Name": 'Ken',
"Age": '',
"Hobbies": [{
'HobbyId': 1,
'HobbyName': 'Swimming'
}, {
'HobbyId': 2,
'HobbyName': 'Reading'
}],
"Skills": [{
'SkillId': 1,
'SkillName': 'PHP'
}, {
'SkillId': 2,
'SkillName': 'MySQL'
}],
"Language": [{
'LangId': 2,
'LangName': 'English'
}, {
'LangId': 3,
'LangName': 'Chinese'
}]
},
{
"Id": 2,
"Name": 'Mike',
"Age": '20',
"Hobbies": [],
"Skills": [],
"Language": []
},
{
"Id": 3,
"Name": 'Charlie',
"Age": '25',
"Hobbies": [{
'HobbyId': 5,
'HobbyName': 'Dance'
}, {
'HobbyId': 6,
'HobbyName': ''
}, {
'HobbyId': 7,
'HobbyName': 'Writing'
}],
"Skills": [],
"Language": [{
'LangId': 7,
'LangName': 'English'
}]
}
];
jQuery.each(arrData, function(key, val) {
arr = [];
generateMaxRows = 1;
jQuery.each(val, function(k, v) {
if (Array.isArray(v)) {
generateMaxRows = (v.length > generateMaxRows) ? v.length : generateMaxRows;
}
});
for (var row = 0; row < generateMaxRows; row++) {
arr = [];
jQuery.each(arrHeader[0], function(header_key, header_val) {
jQuery.each(val, function(row_key, row_val) {
if (row_key == header_val) // Not an array.
{
arr.push(row_val);
} else {
if (Array.isArray(header_val)) {
if (Array.isArray(row_val)) {
jQuery.each(header_val[0], function(head_key, head_val) {
console.log(head_val);
jQuery.each(row_val[row], function(subrow_key, subrow_val) {
if (subrow_key == head_val) {
arr.push(subrow_val);
}
});
});
}
}
}
});
// console.log(arr);
});
finalData.push(arr);
}
});
console.log(JSON.stringify(finalData));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I have done a static array as arrHeader which will have a definition of array items that is to be compared with input array.
I have achieved 90% of the output except the point where I have to pass null values where the arrHeader has an item but arrData does not.
Below is my real example helper array(arrHeader).
var arrHeader= {
"ItemMasterNumber": "ItemMasterNumber",
"IM_Description": "IM_Description",
"IM_FirstProcessDate": "IM_FirstProcessDate",
"IM_Alias": "IM_Alias",
"IM_MasterPrice": "IM_MasterPrice",
"IM_Category": "IM_Category",
"IM_Version": "IM_Version",
"IM_Type": "IM_Type",
"ItemProducts" : [{
"PO_Id" : "PO_Id",
"PO_Code" : "PO_Code",
"PO_Name" : "PO_Name",
"PO_Type" : "PO_Type",
"PO_TaxClassification" : "PO_TaxClassification",
"PO_Bundle" : "PO_Bundle",
"PO_PricingMechanism" : "PO_PricingMechanism",
"PO_StoreVisible" : "PO_StoreVisible",
"PO_NotSoldSeparately" : "PO_NotSoldSeparately",
"PO_EnableDate" : "PO_EnableDate",
"PO_AvailaibilityRule" : "PO_AvailaibilityRule",
"PO_DisableDate" : "PO_DisableDate",
"PO_MinOrderQty" : "PO_MinOrderQty",
"PO_ExpectedReleaseDate" : "PO_ExpectedReleaseDate",
"PO_Description" : "PO_Description",
"PO_GrantOfferingType" : "PO_GrantOfferingType"
}],
"ItemFeatureSet": [{
"FS_Id": "FS_Id",
"FS_Code": "FS_Code",
"FS_Name": "FS_Name",
"FS_Description": "FS_Description",
"FS_EnablementType": "FS_EnablementType"
}],
"ItemFeatures": [{
"FE_Id": "FE_Id",
"FE_Name": "FE_Name",
"FE_Value": "FE_Value"
}],
"ItemCharges": [{
"CH_ChargeId": "CH_ChargeId",
"CH_Name": "CH_Name",
"CH_Description": "CH_Description",
"CH_Type": "CH_Type",
"CH_ProvisioningTag": "CH_ProvisioningTag",
"CH_Currency": "CH_Currency",
"CH_CustomerSegment": "CH_CustomerSegment",
"CH_ExtendedCustomerSegment": "CH_ExtendedCustomerSegment",
"CH_Region": "CH_Region",
"CH_Active": "CH_Active"
}],
"ItemChargeAttributes": [{
"CA_Id": "CA_Id",
"CA_ListPrice": "CA_ListPrice",
"CA_FairValueBasis": "CA_FairValueBasis",
"CA_FairValueMethod": "CA_FairValueMethod",
"CA_FairValueLow": "CA_FairValueLow",
"CA_FairValueHigh": "CA_FairValueHigh",
"CA_EffectiveStartDate": "CA_EffectiveStartDate"
}],
"ItemPackages": [{
"PA_PackageId": "PA_PackageId"
}],
"ItemPackagesComponents": [{
"PA_ComponentId": "PA_ComponentId",
"PA_Type": "PA_Type",
}],
"ItemOffers": [{
"OF_OfferId": "OF_OfferId",
"OF_Name": "OF_Name",
"OF_Description": "OF_Description",
"OF_Level": "OF_Level",
"OF_Type": "OF_Type",
"OF_CustomerSegment" : "OF_CustomerSegment",
"OF_SalesChannel" : "OF_SalesChannel",
"OF_ListPriceOffer" : "OF_ListPriceOffer",
"OF_Region" : "OF_Region",
"OF_CountryCode" : "OF_CountryCode",
"OF_EffectiveStartDate": "OF_EffectiveStartDate",
"OF_EffectiveEndDate": "OF_EffectiveEndDate"
}],
"ItemOffersComponents": [{
"OC_Id": "OC_Id",
"OC_Quantity": "OC_Quantity",
"OC_AdjustmentAmount": "OC_AdjustmentAmount"
}]
};
Can you please help me out with this?
Any help is very much appreciated.
Thanks!

You could use arrHeader with arrays for nested properties. For zeroes, the actual index is used.
var arrHeader = [
'Id',
'Name',
'Age',
['Hobbies', 0, 'HobbyId'],
['Hobbies', 0, 'HobbyName'],
['Skills', 0, 'SkillId'],
['Skills', 0, 'SkillName'],
['Language', 0, 'LangId'],
['Language', 0, 'LangName']
],
data = [{ Id: 1, Name: "Ken", Age: "", Hobbies: [{ HobbyId: 1, HobbyName: "Swimming" }, { HobbyId: 2, HobbyName: "Reading" }], Skills: [{ SkillId: 1, SkillName: "PHP" }, { SkillId: 2, SkillName: "MySQL" }], Language: [{ LangId: 2, LangName: "English" }, { LangId: 3, LangName: "Chinese" }] }, { Id: 2, Name: "Mike", Age: "20", Hobbies: [], Skills: [], Language: [] }, { Id: 3, Name: "Charlie", Age: "25", Hobbies: [{ HobbyId: 5, HobbyName: "Dance" }, { HobbyId: 6, HobbyName: "" }, { HobbyId: 7, HobbyName: "Writing" }], Skills: [], Language: [{ LangId: 7, LangName: "English" }] }],
result = data.reduce(function (r, a) {
var max = arrHeader.reduce(function (m, k) {
return Array.isArray(k) ? Math.max(m, (a[k[0]] || []).length) : m;
}, 1),
i;
for (i = 0; i < max; i++) {
r.push(arrHeader.map(function (k) {
return Array.isArray(k) ? k.reduce(function (v, l) {
return (v || {})[l || i] || '';
}, a) : a[k];
}));
}
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

Consolidate object value containing array : Javascript

I am having array of objects that look like this:
const test = {
cat1: {
id: "c1",
name: "category1",
items: [
{
itemName: "item1",
points: 1,
used: true
},
{
itemName: "item2",
points: 3,
used: false
},
{
itemName: "item3",
points: 5,
used: true
}
]
},
cat2: {
id: "c2",
name: "category2",
items: [
{
itemName: "item4",
points: 7,
used: true
},
{
itemName: "item5",
points: 9,
used: false
}
]
},
cat3: {
id: "c3",
name: "category3",
items: [
{
itemName: "item6"
}
]
}
};
I want the output to be an object something like this
{ available: 12 , used: 13}
Need to go over the items array, and derive the available and used based on if used boolean under each object. If its true, add it with used else add it with available entry.Some object may not have points and used , those need to be ignored.
Can someone help with the approach
Code that I tried
const result = Object.values(test).reduce(
(acc, obj) => {
for (let i = 0; i < obj.items.length; i++) {
if (obj.items[i].used) {
return (acc.used = acc.used + obj.items[i].used);
} else acc.available = acc.available + obj.items[i].available;
}
},
{ available: 0, used: 0 }
);
You could flat the arrays and add with the help of an array.
const
test = { cat1: { id: "c1", name: "category1", items: [{ itemName: "item1", points: 1, used: true }, { itemName: "item2", points: 3, used: false }, { itemName: "item3", points: 5, used: true }] }, cat2: { id: "c2", name: "category2", items: [{ itemName: "item4", points: 7, used: true }, { itemName: "item5", points: 9, used: false }] }, cat3: { id: "c3", name: "category3", items: [{ itemName: "item6" }] } },
result = Object
.values(test)
.flatMap(({ items }) => items)
.reduce((r, { points, used }) => {
if (points) r[['available', 'used'][+used]] += points;
return r;
}, { available: 0 , used: 0 });
console.log(result);
2nd request.
const
test = { cat1: { id: "c1", name: "category1", items: [{ itemName: "item1", points: 1, used: true }, { itemName: "item2", points: 3, used: false }, { itemName: "item3", points: 5, used: true }] }, cat2: { id: "c2", name: "category2", items: [{ itemName: "item4", points: 7, used: true }, { itemName: "item5", points: 9, used: false }] }, cat3: { id: "c3", name: "category3", items: [{ itemName: "item6" }] } },
result = Object
.values(test)
.flatMap(({ items }) => items)
.reduce((r, { points = 0, used = false }) => {
r.used += used && points;
r.available += points;
return r;
}, { available: 0 , used: 0 });
console.log(result);
You're returning on the first iteration of the loop. You need to increment acc.used or acc.available in the loop, but only return acc at the end of the loop.
You need to change the parameter of the callback function to curr to match how you use it inside the function.
obj.items[i].used is not a number to add. You should just increment the counter. And there's no obj.items[i].available.
const test = {
cat1: {
id: "c1",
name: "category1",
items: [{
itemName: "item1",
points: 1,
used: true
},
{
itemName: "item2",
points: 3,
used: false
},
{
itemName: "item3",
points: 5,
used: true
}
]
},
cat2: {
id: "c2",
name: "category2",
items: [{
itemName: "item4",
points: 7,
used: true
},
{
itemName: "item5",
points: 9,
used: false
}
]
},
cat3: {
id: "c3",
name: "category3",
items: [{
itemName: "item6"
}]
}
};
const result = Object.values(test).reduce(
(curr, obj) => {
obj.items.forEach(item => {
if (item.used) {
curr.used++;
} else {
curr.available++;
}
});
return curr;
}, {
available: 0,
used: 0
});
console.log(result);
Do first a map() and .flat(), than the .reduce():
const input = { cat1: { id: "c1", name: "category1", items: [ { itemName: "item1", points: 1, used: true }, { itemName: "item2", points: 3, used: false }, { itemName: "item3", points: 5, used: true } ] }, cat2: { id: "c2", name: "category2", items: [ { itemName: "item4", points: 7, used: true }, { itemName: "item5", points: 9, used: false } ] }, cat3: { id: "c3", name: "category3", items: [ { itemName: "item6" } ] } };
const result = Object.values(input).map(obj => obj.items).flat().reduce((acc, obj) => {
if(obj.used) {
acc.used += obj.points;
} else {
acc.available += obj.points || 0;
}
return acc;
}, {available: 0, used: 0})
console.log(result);
Output:
{
"available": 12,
"used": 13
}
UPDATE 1 to get overall points for available:
const input = { cat1: { id: "c1", name: "category1", items: [ { itemName: "item1", points: 1, used: true }, { itemName: "item2", points: 3, used: false }, { itemName: "item3", points: 5, used: true } ] }, cat2: { id: "c2", name: "category2", items: [ { itemName: "item4", points: 7, used: true }, { itemName: "item5", points: 9, used: false } ] }, cat3: { id: "c3", name: "category3", items: [ { itemName: "item6" } ] } };
const result = Object.values(input).map(obj => obj.items).flat().reduce((acc, obj) => {
acc.available += obj.points || 0;
if(obj.used) {
acc.used += obj.points;
}
return acc;
}, {available: 0, used: 0})
console.log(result);
Output:
{
"available": 25,
"used": 13
}

Append/Add the property to array of objects if match found using javascript

I have two array of objects, in which if id and aid property values match then append the property code to arr1 and return the result
var arr1 = [
{ id: 1, name: "xxx", cn: "IN" },
{ id: 2, name: "yyy", cn: "MY" },
{ id: 3, name: "zzz", cn: "SG" },
]
var arr2 = [
{ aid: 1, code: "finance" },
{ aid: 2, code: "others" },
{ aid: 4, code: "finance" },
{ aid: 5, code: "product" },
]
Expected result:
var arr1 = [
{ id: 1, name: "xxx", cn: "IN", code: 'finance'},
{ id: 2, name: "yyy", cn: "MY", code: 'others'},
{ id: 3, name: "zzz", cn: "SG", code: ''},
]
I tried
var result = arr1.map(e=> ({
...e,
code: arr2.map(i=>i.code)
})
You can do what you require with a loop over arr1 looking for matches in arr2 using filter(). This will add the code property to the existing arr1 array without creating a new array instance.
Note that this logic assumes that there will only ever be 0 or 1 matches in arr2.
var arr1 = [
{ id: 1, name: "xxx", cn: "IN" },
{ id: 2, name: "yyy", cn: "MY" },
{ id: 3, name: "zzz", cn: "SG" },
]
var arr2 = [
{ aid: 1, code: "finance" },
{ aid: 2, code: "others" },
{ aid: 4, code: "finance" },
{ aid: 5, code: "product" },
]
arr1.forEach(o1 => o1.code = arr2.filter(o2 => o2.aid === o1.id)[0]?.code || '');
console.log(arr1);
I am not sure if this is the most optimal solution but this definitely works for your case:
let result = arr1.map((outerObj) => {
// First we try to find the index of the matching object
let index = arr2.findIndex((innerObj) => {
return outerObj.id == innerObj.aid;
});
// In case of no match, set case as "" as per requirement
if(index == -1) {
outerObj.code = "";
return outerObj;
}
// If a match is found, then combine the two objects.
let mergedObj = { ...outerObj, ...arr2[index]};
// aid is not needed in the result, Who wants aids anyway?
delete mergedObj.aid;
return mergedObj;
});
If not more optimal, then definitely there could be smaller code but I think the code should be clear and readable rather than being smaller.
First, massage the data into a format for fast manipulation; then manipulate.
The following:
Puts every item in arr2 into a map, keyed on aid
Enumerates arr1 once, looking into the map for each item to see if there is a corresponding code
Performance: O(N).
var arr1= [
{id:1, name: "xxx", cn: "IN"},
{id:2, name: "yyy", cn: "MY"},
{id:3, name: "zzz", cn: "SG"} ]
var arr2 = [
{ aid: 1, code: "finance"},
{ aid: 2, code: "others"},
{ aid: 4, code: "finance"},
{ aid: 5, code: "product"} ]
const map = arr2.reduce((p,c) => p.set(c.aid, c), new Map)
arr1.forEach((i) => i.code = map.get(i.id)?.code || '')
console.log(arr1)
You need to first find matching item in arr2 and them create the composed item.
Try like this:
var arr1 = [
{ id: 1, name: "xxx", cn: "IN" },
{ id: 2, name: "yyy", cn: "MY" },
{ id: 3, name: "zzz", cn: "SG" },
];
var arr2 = [
{ aid: 1, code: "finance" },
{ aid: 2, code: "others" },
{ aid: 4, code: "finance" },
{ aid: 5, code: "product" },
];
const result = arr1.map((item) => {
const match = arr2.find((o) => o.aid === item.id);
return { ...item, code: match ? match.code : '' };
});
console.log(result);
we can get like this too
var arr1 = [
{ id: 1, name: "xxx", cn: "IN" },
{ id: 2, name: "yyy", cn: "MY" },
{ id: 3, name: "zzz", cn: "SG" },
]
var arr2 = [
{ aid: 1, code: "finance" },
{ aid: 2, code: "others" },
{ aid: 4, code: "finance" },
{ aid: 5, code: "product" },
]
const fun = (ar, ar2)=>{
const getResult = ar.map((e)=> {
const Data ={
id : e.id,
name : e.name,
cn : e.cn,
code : ar2.find((e2)=> e2.aid===e.id)?.code || ""
}
return Data;
})
return getResult
}
console.log(fun(arr1, arr2))
we can usefind method too
var arr1 = [
{ id: 1, name: "xxx", cn: "IN" },
{ id: 2, name: "yyy", cn: "MY" },
{ id: 3, name: "zzz", cn: "SG" },
]
var arr2 = [
{ aid: 1, code: "finance" },
{ aid: 2, code: "others" },
{ aid: 4, code: "finance" },
{ aid: 5, code: "product" },
]
arr1.forEach(e => e.code = arr2.find(d => d.aid === e.id)?.code || '');
console.log(arr1);

Change objects structure

I have an array of objects:
const res = [
{
KIND_ID: 2229,
NAME: "Group",
SKU_ID: 311,
ARTICLE_NAME: "Product one",
WEEK: 202027,
FORECAST: 81928.37,
PROMO: 0,
SALES: 92848,
SAFETY_STOCK: 57704.79,
STORES_COUNT: 132,
ADD_FCST: null
},
{
KIND_ID: 2229,
NAME: "Group",
SKU_ID: 311,
ARTICLE_NAME: "Product one",
WEEK: 202028,
FORECAST: 84278.85,
PROMO: 0,
SALES: null,
SAFETY_STOCK: 64000.39,
STORES_COUNT: 144,
ADD_FCST: null
},
{
KIND_ID: 2229,
NAME: "Group",
SKU_ID: 316,
ARTICLE_NAME: "Product two",
WEEK: 202027,
FORECAST: 89112.97,
PROMO: 0,
SALES: 98007,
SAFETY_STOCK: 59509.31,
STORES_COUNT: 142,
ADD_FCST: null
},
{
KIND_ID: 2229,
NAME: "Group",
SKU_ID: 316,
ARTICLE_NAME: "Product two",
WEEK: 202028,
FORECAST: 85129.4,
PROMO: 0,
SALES: null,
SAFETY_STOCK: 63409.61,
STORES_COUNT: 144,
ADD_FCST: null
}
];
I want to group some fields in WEEKS, e.g:
const expected = [
{
KIND_ID: 2229,
NAME: "Group",
SKU_ID: 311,
ARTICLE_NAME: "Product one",
FORECAST: [{ 202026: 97555.64 }, { 202027: 98336.45 }],
PROMO: [{ 202026: 0 }, { 202027: 0 }],
SALES: [{ 202026: 95911.77 }, { 202027: null }],
SAFETY_STOCK: [{ 202026: 63622.28 }, { 202027: 72852.62 }],
STORES_COUNT: [{ 202026: 135 }, { 202027: 143 }],
ADD_FCST: [{ 202026: null }, { 202027: null }]
},
{
KIND_ID: 2229,
NAME: "Group",
SKU_ID: 316,
ARTICLE_NAME: "Product two",
FORECAST: [{ 202026: 104125.69 }, { 202027: 101147.07 }],
PROMO: [{ 202026: 0 }, { 202027: 0 }],
SALES: [{ 202026: 102281 }, { 202027: null }],
SAFETY_STOCK: [{ 202026: 53709.55 }, { 202027: 60675.26 }],
STORES_COUNT: [{ 202026: 143 }, { 202027: 144 }],
ADD_FCST: [{ 202026: null }, { 202027: null }]
}
];
If it helps i have array of weeks and values need to be grouped:
const weeks = [202027, 202028];
const keys = ['FORECAST','PROMO','SALES','SAFETY_STOCK','STORES_COUNT','ADD_FCST'];
I tried to solve with reduce and underscore method groupBy but this not helped. How to group this res array to expected?
Dummy text, because: It looks like your post is mostly code; please add some more details. But that's all what i want to tell
I tried to solve with reduce
That's what I'd use, although there is a few steps involved as this isn't a classic grouping schematic.
Below is an example.
const res=[{KIND_ID:2229,NAME:"Group",SKU_ID:311,ARTICLE_NAME:"Product one",WEEK:202027,FORECAST:81928.37,PROMO:0,SALES:92848,SAFETY_STOCK:57704.79,STORES_COUNT:132,ADD_FCST:null},{KIND_ID:2229,NAME:"Group",SKU_ID:311,ARTICLE_NAME:"Product one",WEEK:202028,FORECAST:84278.85,PROMO:0,SALES:null,SAFETY_STOCK:64000.39,STORES_COUNT:144,ADD_FCST:null},{KIND_ID:2229,NAME:"Group",SKU_ID:316,ARTICLE_NAME:"Product two",WEEK:202027,FORECAST:89112.97,PROMO:0,SALES:98007,SAFETY_STOCK:59509.31,STORES_COUNT:142,ADD_FCST:null},{KIND_ID:2229,NAME:"Group",SKU_ID:316,ARTICLE_NAME:"Product two",WEEK:202028,FORECAST:85129.4,PROMO:0,SALES:null,SAFETY_STOCK:63409.61,STORES_COUNT:144,ADD_FCST:null}];
const grpFields = ['FORECAST', 'PROMO', 'SALES', 'SAFETY_STOCK',
'STORES_COUNT', 'ADD_FCST'];
const o = res.reduce((a, v) => {
const {KIND_ID, NAME, SKU_ID, ARTICLE_NAME} = v;
let f = a.find(f => f.SKU_ID === v.SKU_ID);
if (!f) {
f = {KIND_ID, NAME, SKU_ID, ARTICLE_NAME};
grpFields.forEach(k => f[k] = []);
a.push(f);
}
grpFields.forEach(k => f[k].push({[v.WEEK]: v[k]}));
return a;
},[]);
console.log(o);
To make this a generic function, you will need to pass a few parameters.
Below is an example.
arr = The array your wanting to group
grpFields = The fields that you want the grouping applied to
grpValue = The field value your grouping
keyField = What field we are grouping on
stdFields = Other fields you want as part of the result
const res=[{KIND_ID:2229,NAME:"Group",SKU_ID:311,ARTICLE_NAME:"Product one",WEEK:202027,FORECAST:81928.37,PROMO:0,SALES:92848,SAFETY_STOCK:57704.79,STORES_COUNT:132,ADD_FCST:null},{KIND_ID:2229,NAME:"Group",SKU_ID:311,ARTICLE_NAME:"Product one",WEEK:202028,FORECAST:84278.85,PROMO:0,SALES:null,SAFETY_STOCK:64000.39,STORES_COUNT:144,ADD_FCST:null},{KIND_ID:2229,NAME:"Group",SKU_ID:316,ARTICLE_NAME:"Product two",WEEK:202027,FORECAST:89112.97,PROMO:0,SALES:98007,SAFETY_STOCK:59509.31,STORES_COUNT:142,ADD_FCST:null},{KIND_ID:2229,NAME:"Group",SKU_ID:316,ARTICLE_NAME:"Product two",WEEK:202028,FORECAST:85129.4,PROMO:0,SALES:null,SAFETY_STOCK:63409.61,STORES_COUNT:144,ADD_FCST:null}];
function groupData(arr, grpFields, grpValue, keyField, stdFields) {
return arr.reduce((a, v) => {
let f = a.find(f => f[keyField] === v[keyField]);
if (!f) {
f = Object.fromEntries(stdFields.map(k => [k, v[k]]));
grpFields.forEach(k => f[k] = []);
a.push(f);
}
grpFields.forEach(k => f[k].push({[v[grpValue]]: v[k]}));
return a;
},[]);
}
console.log(
groupData(
res,
['FORECAST', 'PROMO', 'SALES', 'SAFETY_STOCK','STORES_COUNT', 'ADD_FCST'],
'WEEK',
'SKU_ID',
['KIND_ID', 'NAME', 'SKU_ID', 'ARTICLE_NAME']
)
);

Check if an element is common between 2 arrays and then assign values from it

In my angular 8 application, I have 2 arrays:
array1 = [{
"SubType": "2|3|4|5|6",
},
{
"SubType": "2",
},
{
"SubType": "3|4",
},
{
"SubType": "6",
},
{
"SubType": "3|6",
},
]
&
array2 = [{
"id": 2,
"type": "1",
},
{
"id": 3,
"type": "5",
},
{
"id": 4,
"type": "4",
},
{
"id": 5,
"type": "3",
},
{
"id": 6,
"type": "2",
}
]
I am trying to check each "SubType" in array1 and see if that element(id) is present in array2 and if present assign its "type" to a variable. "SubType" is | separated which I and converting to an array using array1..split('|'). This when assigning to a variable will need to be comma separated. I tried using array filter but I am not able to find a way to loop thorough the second array. Can anyone help?
array1.forEach(reg => {
if (reg.SubType) {
let subTypeTemp = reg.SubType.split('|');
let tempVariable = subTypeTemp.some(ele => {
let stringToassign = '';
for (let i = 0; i < array2.length; i++) {
if (ele == array2[i].id) {
stringToassign += array2[i].type + ",";
}
}
})
}
})
const array1 = [
{
SubType: "2|3|4|5|6"
},
{ SubType: "2" },
{ SubType: "3|4" },
{ SubType: "6" },
{ SubType: "3|6" }
];
const array2 = [
{
id: 2,
type: "1"
},
{ id: 3, type: "5" },
{ id: 4, type: "4" },
{ id: 5, type: "3" },
{ id: 6, type: "2" }
];
const array2Obj = array2.reduce(
(acc, curr) => ({
...acc,
[curr.id]: curr.type
}),
{}
);
const types = [];
array1.forEach(item => {
const sub_types = item.SubType.split("|");
sub_types.forEach(st => {
if (st in array2Obj) {
types.push(array2Obj[st]);
}
});
});
const types_str = [...new Set(types)].join(',');
console.log("types", types_str);
You could take a Map and prevent looping array2 over and over for getting type of a wanted id.
var array1 = [{ SubType: "2|3|4|5|6" }, { SubType: "2" }, { SubType: "3|4" }, { SubType: "6" }, { SubType: "3|6" }],
array2 = [{ id: 2, type: "1" }, { id: 3, type: "5" }, { id: 4, type: "4" }, { id: 5, type: "3" }, { id: 6, type: "2" }],
types = new Map(array2.map(({ id, type }) => [id.toString(), type])),
result = array1.map(({ SubType }) => SubType
.split('|')
.map(Map.prototype.get, types)
.join()
);
console.log(result);

Retrieving value from two arrays

I have two arrays.
STUD = [{"id":1,"name":"Kida"},{"id":2,"name":"Kidb"},{"id":3,"name":"Kidc"},{"id":4,"name":"Kidd"},{"id":5,"name":"Kide"}]
IDCRD = [{"id":3,"status":"Y"},{"id":4,"status":"Y"},{"id":2,"status":"N"},{"id":5,"status":"Y"},{"id":1,"status":"N"}]
Then I have a loop:
for(var i=0;i<STUD.length;i++){
var id = STUD[i][0];
var name = STUD[i][1];
var status = ?
}
I need the status for STUD[i] from IDCRD array having the same ID inside this loop.
Have another loop on IDCRD and match ids of STUD and IDCRD then get the status
STUD = [{
"id": 1,
"name": "Kida"
}, {
"id": 2,
"name": "Kidb"
}, {
"id": 3,
"name": "Kidc"
}, {
"id": 4,
"name": "Kidd"
}, {
"id": 5,
"name": "Kide"
}];
IDCRD = [{
"id": 3,
"status": "Y"
}, {
"id": 4,
"status": "Y"
}, {
"id": 2,
"status": "N"
}, {
"id": 5,
"status": "Y"
}, {
"id": 1,
"status": "N"
}];
for (var i = 0; i < STUD.length; i++) {
var id = STUD[i].id;
var name = STUD[i].name;
for (j = 0; j < IDCRD.length; j++) {
if (STUD[i].id == IDCRD[j].id) {
var status = IDCRD[j].status;
}
}
console.log(id, name, status);
}
The function status should do what you need
var STUD = [{"id":1,"name":"Kida"},{"id":2,"name":"Kidb"},{"id":3,"name":"Kidc"},{"id":4,"name":"Kidd"},{"id":5,"name":"Kide"}];
var IDCRD = [{"id":3,"status":"Y"},{"id":4,"status":"Y"},{"id":2,"status":"N"},{"id":5,"status":"Y"},{"id":1,"status":"N"}];
function status(i){ return IDCRD.filter(w => w.id == STUD[i].id)[0].status }
console.log(status(0));
console.log(status(1));
console.log(status(2));
console.log(status(3));
console.log(status(4));
or if you run with Node you can write
status = i => IDCRD.filter(w => w.id == STUD[i].id)[0].status
You could take a Map and use id as key and take the map for an easy access to the data of IDCRD.
var stud = [{ id: 1, name: "Kida" }, { id: 2, name: "Kidb" }, { id: 3, name: "Kidc" }, { id: 4, name: "Kidd" }, { id: 5, name: "Kide" }],
IDCRD = [{ id: 3, status: "Y" }, { id: 4, status: "Y" }, { id: 2, status: "N" }, { id: 5, status: "Y" }, { id: 1, status: "N" }],
map = IDCRD.reduce((m, o) => m.set(o.id, o), new Map),
result = stud.map(o => Object.assign({}, o, map.get(o.id)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Another solution could be using Array#find, but this approach iterates the array for each item to find.
var stud = [{ id: 1, name: "Kida" }, { id: 2, name: "Kidb" }, { id: 3, name: "Kidc" }, { id: 4, name: "Kidd" }, { id: 5, name: "Kide" }],
IDCRD = [{ id: 3, status: "Y" }, { id: 4, status: "Y" }, { id: 2, status: "N" }, { id: 5, status: "Y" }, { id: 1, status: "N" }],
result = stud.map(o => Object.assign({}, o, IDCRD.find(({ id }) => id === o.id)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories