How to find the number that best matches a given number - javascript

How to find the most suitable number for a given number.
For example. I have a number 8 and an array of objects.
let num = 8;
let data = [
{ fist: {a: 1, b: 2}, second: {c: 11, d: 12}, number: 1 },
{ fist: {a: 3, b: 4}, second: {c: 13, d: 14}, number: 7 },
{ fist: {a: 5, b: 6}, second: {c: 15, d: 16}, number: 10 },
];
The closest number of all numbers in each object is 7.
How can I display the whole obit to which the number 7 belongs?

You can use .reduce to get the obj with minimum distance from num:
let num = 8;
let data = [
{ fist: {a: 1, b: 2}, second: {c: 11, d: 12}, number: 1 },
{ fist: {a: 3, b: 4}, second: {c: 13, d: 14}, number: 7 },
{ fist: {a: 5, b: 6}, second: {c: 15, d: 16}, number: 10 },
];
const _isEmpty = (obj) => Object.keys(obj).length === 0;
const objWithClosestNumber = data.reduce((acc, item) => {
if(_isEmpty(acc)) { return item };
const closestDist = Math.abs(num - acc.number),
currentDist = Math.abs(num - item.number);
acc = (currentDist < closestDist) ? item : acc;
return acc;
}, {});
console.log(objWithClosestNumber);

Traverse the array and find the smallest difference.
let num = 8;
let data = [
{ fist: { a: 1, b: 2 }, second: { c: 11, d: 12 }, number: 1 },
{ fist: { a: 3, b: 4 }, second: { c: 13, d: 14 }, number: 7 },
{ fist: { a: 5, b: 6 }, second: { c: 15, d: 16 }, number: 10 },
];
let diff = Math.abs(num - data[0].number);
let ret = data[0];
data.forEach((x) => {
if (diff > Math.abs(x.number - num)) {
diff = Math.abs(x.number - num);
ret = x;
}
});
console.log(ret);

You could reduce the array by choosing the item with the smaller absolute delta of given value and wanted value .
let num = 8,
data = [{ fist: { a: 1, b: 2 }, second: {c: 11, d: 12 }, number: 1 }, { fist: { a: 3, b: 4 }, second: { c: 13, d: 14 }, number: 7 }, { fist: { a: 5, b: 6 }, second: { c: 15, d: 16 }, number: 10 }],
result = data.reduce((a, b) =>
Math.abs(num - a.number) < Math.abs(num - b.number) ? a : b
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

problem with reduce and memoisation in javascript hardstructure

i have to do a task, where i need to iterate over hardstructure with nested functions arrays objects and other data types. get all the numbers there are in string or not in string into the array and then with reduce method i need to calculate their sum, after calculating their sum i need to do memoisation on this function. but something doesnt work with my reduce even though i have written the most simple task there is, calculating the sum of numbers. my reduce doesnt really calculate the right way it skips some parts of the structure and doesnt gather all of the nubmers also it doesnt really calculate right i think
const ex1 = () => ({ a: 13 });
const ex2 = () => [1, 2, 3, 4, 5, "a,,,,,,", 2, 2, 2];
const ex3 = () => [...ex2()];
const ex4 = new Set([1, 2, 3, 4]);
const hardStructure = [
{
a: 1,
b: "2",
c: [
{
a: "123",
b: "#333z$34",
c: "122,333,4444,5555",
z: ex4,
d: [
[
123,
1,
"1111",
23323,
1222,
55,
[1212, 1212, 1212],
{
a: 111,
b: null,
c: () => 111,
d: 22,
e: "e",
f: () => "fffqqq",
},
],
[
2212,
1,
"111211",
23,
121,
22,
[33, 3, 3],
{
a: 3,
b: null,
c: () => 11221,
d: 2112,
e: "e11",
f: () => "fffqqq",
g: 2,
},
],
[
11,
22,
"dsds",
{
a: {
b: {
c: {
d: {
a: 1,
b: [ex1()],
c: {
a: {
b: {
c: {
d: {
a: new Map([
["a2134", 2123123],
["b", 3],
["c", 3],
]),
b: ex2,
c: [...ex3(), "1", 1],
},
},
},
},
},
},
},
},
},
},
],
],
},
],
},
{
d: [
[
123,
1,
"1111",
23323,
1222,
55,
[121322332, 12132322, 12323212],
{
a: 111,
b: null,
c: () => 1123231,
d: 22,
e: "e",
f: () => "fffqqq",
},
],
[
2212,
1,
"111211",
23,
121,
22,
[33, 3, 3],
{
a: 3,
b: null,
c: () => 1123221,
d: 211,
e: "e1231",
f: () => "fffqq1232312123q",
g: 2123,
},
],
[
11,
22,
"dsds",
{
a: {
b: {
c: {
d: {
a: 1,
b: [ex1()],
c: {
a: {
b: {
c: {
d: {
a: new Map([
[true, 222312],
[2, 322],
["c2", 32],
[() => {}, 32],
]),
b: ex2,
c: [...ex3(), "1121123", 1],
},
},
},
},
},
},
},
},
},
},
],
],
},
{
a: {
b: {
c: {
d: {
a: 112312,
b: [1],
c: {
a: {
b: {
c: {
d: {
a: "",
b: "",
c: "",
v: "v12312323",
},
},
},
},
},
},
},
},
},
},
];
const numbersArr = [];
const iterate = (hardStructure) => {
if (hardStructure === null || hardStructure === undefined) {
return [];
}
if (
hardStructure.constructor === new Set().constructor ||
hardStructure.constructor === new Map().constructor
) {
console.log("console from map or set");
hardStructure.forEach((element) => {
// console.log("123", element);
return iterate(element);
});
}
if (typeof hardStructure === "function") {
return iterate(hardStructure());
}
if (Array.isArray(hardStructure)) {
hardStructure.map((items) => {
return iterate(items);
});
}
if (typeof hardStructure === "object" && !Array.isArray(hardStructure)) {
for (let key in hardStructure) {
// console.log(hardStructure[key]);
return iterate(hardStructure[key]);
}
}
if (typeof hardStructure !== "string") {
const stringItem = String(hardStructure);
for (let i = 0; i < stringItem.length; i++) {
if (!isNaN(+stringItem)) {
numbersArr.push(+stringItem);
}
}
}
for (let i = 0; i < hardStructure.length; i++) {
// console.log(i);
if (!isNaN(+hardStructure[i])) {
// console.log("12345678910", isNaN(+hardStructure[2]));
numbersArr.push(+hardStructure[i]);
}
}
const sumWithInitial = numbersArr.reduce((accumulator, currentValue) => {
console.log(accumulator,currentValue)
return accumulator + currentValue;
},0);
// console.log(numbersArr)
console.log(sumWithInitial);
return sumWithInitial;
};
iterate(hardStructure);
Your requirements aren't entirely clear, especially as to handling of String and Function properties. This solution assumes that you want to call functions and that you can use parseInt for Strings. If you need to change that, it should be clear enough how and where to do so:
const sumNumbers = (xs) =>
xs == null
? 0
: xs .constructor == String
// ? parseInt (xs, 10) || 0 // original version not enough. Below might not be so either
? xs .includes (',') ? sumNumbers (xs .split (',')) : Number (xs .replaceAll (/\D/g, ''))
: xs .constructor == Number
? xs
: xs .constructor === Array
? xs .map (sumNumbers) .reduce ((a, b) => a + b, 0)
: xs .constructor === Set
? sumNumbers ([...xs])
: xs .constructor === Map
? sumNumbers ([...xs .values()])
: xs .constructor === Function
? sumNumbers (xs ()) // or just 0?
: xs .constructor == Object
? sumNumbers (Object .values (xs))
// TODO: Other types possible here?
: 0
const ex1 = () => ({a: 13}),
ex2 = () => [1, 2, 3, 4, 5, "a,,,,,,", 2, 2, 2],
ex3 = () => [...[1, 2, 3, 4, 5, "a,,,,,,", 2, 2, 2]],
ex4 = new Set ([1, 2, 3, 4]),
hardStructure = [{a: 1, b: "2", c: [{a: "123", b: "#333z$34", c: "122,333,4444,5555", z: ex4, d: [[123, 1, "1111", 23323, 1222, 55, [1212, 1212, 1212], {a: 111, b: null, c: () => 111, d: 22, e: "e", f: () => "fffqqq"}], [2212, 1, "111211", 23, 121, 22, [33, 3, 3], {a: 3, b: null, c: () => 11221, d: 2112, e: "e11", f: () => "fffqqq", g: 2}], [11, 22, "dsds", {a: {b: {c: {d: {a: 1, b: [{a: 13}], c: {a: {b: {c: {d: {a: new Map ([["a2134", 2123123], ["b", 3], ["c", 3]]), b: ex2, c: [...ex3(), "1", 1]}}}}}}}}}}]]}]}, {d: [[123, 1, "1111", 23323, 1222, 55, [121322332, 12132322, 12323212], {a: 111, b: null, c: () => 1123231, d: 22, e: "e", f: () => "fffqqq"}], [2212, 1, "111211", 23, 121, 22, [33, 3 , 3], {a: 3, b: null, c: () => 1123221, d: 211, e: "e1231", f: ()=> "fffqq1232312123q", g: 2123}], [11, 22, "dsds", {a: {b: {c: {d: {a: 1, b: [{a: 13}], c: {a: {b: {c: {d: {a: new Map ([[true, 222312], [2, 322], ["c2", 32], [() => {}, 32]]), b: ex2, c: [...ex3 (), "1121123", 1]}}}}}}}}}}]]}, {a: {b: {c: {d: {a: 112312, b: [1], c: {a: {b: {c: {d: {a: "", b: "", c: "", v: "v12312323"}}}}}}}}}}]
console .log (sumNumbers (hardStructure))
We have four base cases:
on a nil value (null or undefined), we return 0
on a Number, we return its value
on a String, we call parseInt on it and return the value. This is the part I think you would most likely need to change
on an unknown type (perhaps a regular expression or a date), we return 0
The others are recursive case:
for an Array, we recursively call our function on each element and then total them together.
for a Function, we call the function with no arguments, and recur on the result.
for our other known types (Object, Set, Map), we extract its values into an Array and recur on the result.

I want to create an object with the key as a property from the object and value as an array of objects matching the key (javascript)

I have a given object to iterate and create another object in the below format (newObj)
Given object:
let obj = [
{a: 1, b: 232},
{a: 1, b: 2},
{a: 1, b: 256},
{a: 2, b: 3},
{a: 2, b: 3343},
{a: 3, b: 4}
];
Expected object:
newObj = {
1: [{a: 1, b: 232}, {a: 1, b: 2}, {a: 1, b: 256}],
2: [{a: 2, b: 3}],
3: [{a: 3, b: 4}]
}
Code:
let newObj = {};
obj.forEach(element => {
if (newObj[element.a]) {
let key = element.a;
newObj[key] = newObj[key].push(element);
}
newObj[element.a] = [element];
});
console.log(newObj);
We create a result object, loop through every object in obj array, if we don't have the object a key in the result object, we add him (a: []), and after that we push the entire object to result[a] array
let obj = [
{a: 1, b: 232},
{a: 1, b: 2},
{a: 1, b: 256},
{a: 2, b: 3},
{a: 2, b: 3343},
{a: 3, b: 4}
];
let result = {};
for(const {a, b} of obj) {
if(!result[a]) result[a] = []
result[a].push({a, b})
}
console.log(result)
To address your updated code snippet, you need to only create a new array for a given key if they key does not exist.
let obj = [
{ a: 1, b: 232 },
{ a: 1, b: 2 },
{ a: 1, b: 256 },
{ a: 2, b: 3 },
{ a: 2, b: 3343 },
{ a: 3, b: 4 }
];
let newObj = {};
obj.forEach(element => {
let key = element.a;
if (!newObj[key]) {
newObj[key] = []; // Only initialize if undefined/null
}
newObj[key].push(element); // Always push
});
console.log(newObj);
.as-console-wrapper { top: 0; max-height: 100% !important; }
A more modern approach would be to simply bin them by the a key by reducing and spreading.
const obj = [
{ a: 1, b: 232 },
{ a: 1, b: 2 },
{ a: 1, b: 256 },
{ a: 2, b: 3 },
{ a: 2, b: 3343 },
{ a: 3, b: 4 }
];
const newObj = obj.reduce((acc, o) => ({
...acc,
[o.a]: [...(acc[o.a] ?? []), o]
}), {});
console.log(newObj);
.as-console-wrapper { top: 0; max-height: 100% !important; }
you can use reduce for that
let obj = [
{a: 1, b: 232},
{a: 1, b: 2},
{a: 1, b: 256},
{a: 2, b: 3},
{a: 2, b: 3343},
{a: 3, b: 4}
];
const newObj = obj.reduce((res, {a, b}) => {
return {
...res,
[a] : [...(res[a] || []), {a, b}]
}
}, {})
console.log(newObj)

Finding all the keys in the array of objects

Given that I have an array that is return from database that contains object,
var jsObjects = [
{a: 1, b: 2},
{a: 3, b: 4, c: 66},
{a: 5, b: 6, c: 55, d: 66},
{a: 7, b: 8, c: 12, e: 15}
];
How can I get all the keys of the object? I've been using this to obtain the keys, however I notice that index 0 wont always have all the keys. Hence problem lays.
let columns = Object.keys(jsObjects[0]),
However, the first index won't always have all the columns.
My desired output:
["a", "b", "c", "d", "e"]
Sets are good at removing duplicates:
const jsObjects = [
{a: 1, b: 2},
{a: 3, b: 4, c: 66},
{a: 5, b: 6, c: 55, d: 66},
{a: 7, b: 8, c: 12, e: 15}
];
const keys = [...new Set(jsObjects.flatMap(Object.keys))];
console.log(keys);
You could create an object with the count of the keys and get the keys from counts.
const
objects = [{ a: 1, b: 2 }, { a: 3, b: 4, c: 66 }, { a: 5, b: 6, c: 55, d: 66 }, { a: 7, b: 8, c: 12, e: 15 }],
result = Object.keys(objects.reduce((r, o) => {
Object.keys(o).forEach(k => r[k] = true);
return r;
}));
console.log(result);
You can use a Set(), which is like an array with the exception that it doesn't allow multiple occurances of elements.
var jsObjects = [
{a: 1, b: 2},
{a: 3, b: 4, c: 66},
{a: 5, b: 6, c: 55, d: 66},
{a: 7, b: 8, c: 12, e: 15}
];
var keys = new Set();
for(object of jsObjects) {
for(key in object) {
keys = keys.add(key);
}
}
for (const key of keys) {
console.log(key);
}
I tried this solution: iterating on jsObjects elements and pushing keys
into columns array if not present.
var jsObjects = [
{a: 1, b: 2},
{a: 3, b: 4, c: 66},
{a: 5, b: 6, c: 55, d: 66},
{a: 7, b: 8, c: 12, e: 15}
];
let columns = [];
jsObjects.forEach(
o => {
Object.keys(o).forEach(
t => {
if (columns.indexOf(t) < 0 ) {
columns.push(t);
}
}
)
}
)
console.log(columns);

Compare two nested array and objects for find difference

I have two JSON data with multi-stage nesting. I want compare it by following conditions:
1) if name in the first object equal to name in the second object compare them prop arrays, else if nothing equal names in two object return empty array;
2) compare objects into two prop arrays and find difference;
3) return new object with difference from first and second arrays.
const p1 = [{
name: 'B [1]', // name equals and prop differnce, then comparing it
prop: [{
A: { A: 1, B: 2 },
B: { A: 1, B: 2 },
C: { C: 78, D: 4, T: 7, } }],
}, {
name: 'B [2]', // name equals, then skiping it
prop: [{
A: { A: 1, B: 2 },
B: { A: 1, B: 2 },
D: { C: 3, D: 4, Y: 13 } }],
}, {
name: 'B [3]', // name equals and prop differnce, then comparing it
prop: [{
E: { A: 1, B: 2 },
R: { A: 1, B: 2 },
T: { C: 3, D: 4, } }],
}, {
name: 'B [4]', // name and prop equals, then skiping it
prop: [{
A: { A: 1, B: 2 },
S: { A: 1, B: 2 },
D: { C: 3, D: 4, } }],
}]
const p2 = [{
name: 'B [1]', // name equals and prop differnce, then comparing it
prop: [{
A: { A: 1, B: 8 },
B: { A: 1, B: 2 },
C: { C: 3, T: 7, O: 9 } }],
}, {
name: 'B [6]', // name not equals, then skiping it
prop: [{
A: { A: 1, B: 2 },
B: { A: 1, B: 2 },
D: { C: 3, D: 4 } }],
}, {
name: 'B [3]', // name equals and prop differnce, then comparing it
prop: [{
E: { A: 1, B: 2 },
R: { A: 1, B: 2, U: 150 },
T: { C: 3, D: 4, } }],
}, {
name: 'B [4]', // name and prop equals, then skiping it
prop: [{
A: { A: 1, B: 2 },
S: { A: 1, B: 2 },
D: { C: 3, D: 4, } }],
}]
The result should look like this:
const result = [{
name: 'B [1]',
propOne: [{
A: { B: 2 },
C: { C: 78, D: 4, O: 'Missing' }
}],
propTwo: [{
A: { B: 8 },
C: { C: 3, D: 'Missing', O: 9 }
}],
},{
name: 'B [3]',
propOne: [{
R: { U: 'Missing' }
}],
propTwo: [{
R: { U: 150 }
}]
}]
I also bitterly attach my worthless code here, which does nothing.
const compare = (p1, p2) => {
return p1.reduce((acc, curr) => {
p2.reduce((acc2, curr2) => {
if (curr.name === curr2.name) {
const keys1 = R.fromPairs(Object.keys(curr.prop[0]).map(x => ([x, curr.prop[0][x]])));
const keys2 = R.fromPairs(Object.keys(curr2.prop[0]).map(x => ([x, curr2.prop[0][x]])));
}
return acc;
}, [])
return acc;
}, [])
}
I would be extremely grateful for any help and advice.
All the difficulty resides in specing the expected behaviour of the comparison function:
for two objects (that I refer as values) a and b: {A:1,B:2} and {A:1,B:3,C:4}
the output of cmp(a,b) shall be:
foreach key of a:
if a[key] != b[key] (or b does not have k prop)
diff[key] = a[key]
else (value is equal, no diff)
foreach key of b not in a
diff[key] = Missing
hence (e.g) {B:2, C:'Missing'}
when comparing the values, if diff is empty, you can skip the current prop and when comparing props if the diff is empty skip the record (as if names were different)
function cmp(x,y){
let a = x.prop[0];
let b = y.prop[0];
return Object.keys(a).reduce((o,k)=>{
//compare the right value (such as { A: 1, B: 2 }). assumes primitive types
let u = a[k];
let v = b[k];
let diff = Object.keys(u).reduce((o,k)=>{
return u[k]==v[k]?o:(o[k] = u[k],o)
},{})
Object.keys(v).reduce((o,k)=>{
return u.hasOwnProperty(k)?o:(o[k]='Missing',o);
}, diff);
if(Object.keys(diff).length){
o[k] = diff;
}
return o;
},{});
}
function diff(p1,p2){
return p1.flatMap((o,i)=>{
if(p2[i].name != p1[i].name){
return []
}
let a = p1[i];
let b = p2[i];
let res = cmp(a,b);
if(!Object.keys(res).length){
return [];
}
return {name: a.name, propOne:res, propTwo:cmp(b,a)}
})
};
const p1 = [{
name: 'B [1]', // name equals and prop differnce, then comparing it
prop: [{
A: { A: 1, B: 2 },
B: { A: 1, B: 2 },
C: { C: 78, D: 4, T: 7, } }],
}, {
name: 'B [2]', // name equals, then skiping it
prop: [{
A: { A: 1, B: 2 },
B: { A: 1, B: 2 },
D: { C: 3, D: 4, Y: 13 } }],
}, {
name: 'B [3]', // name equals and prop differnce, then comparing it
prop: [{
E: { A: 1, B: 2 },
R: { A: 1, B: 2 },
T: { C: 3, D: 4, } }],
}, {
name: 'B [4]', // name and prop equals, then skiping it
prop: [{
A: { A: 1, B: 2 },
S: { A: 1, B: 2 },
D: { C: 3, D: 4, } }],
}]
const p2 = [{
name: 'B [1]', // name equals and prop differnce, then comparing it
prop: [{
A: { A: 1, B: 8 },
B: { A: 1, B: 2 },
C: { C: 3, T: 7, O: 9 } }],
}, {
name: 'B [6]', // name not equals, then skiping it
prop: [{
A: { A: 1, B: 2 },
B: { A: 1, B: 2 },
D: { C: 3, D: 4 } }],
}, {
name: 'B [3]', // name equals and prop differnce, then comparing it
prop: [{
E: { A: 1, B: 2 },
R: { A: 1, B: 2, U: 150 },
T: { C: 3, D: 4, } }],
}, {
name: 'B [4]', // name and prop equals, then skiping it
prop: [{
A: { A: 1, B: 2 },
S: { A: 1, B: 2 },
D: { C: 3, D: 4, } }],
}];
console.log('result', JSON.stringify(diff(p1,p2),null,2))
It's kinda late, and i don't have time anymore for extensive tests right now, so this may have some bugs for unexpected cases (i hope not though). It's way too long for a comment, and discarding it would be a bit of a waste.
The below code contains two ways: one constructive, starting with empty objects, building up, and one the other way around, starting with the full objects, and then deleting.
Note, that in your data structures, there are several "one element arrays". If these can contain more than one element (they don't really make much sense to me, it's already objects within arrays within arrays, giving plenty of room for additional props), there needs to be one or two extra map steps, no big issue though.
const p1 = [{
name: 'B [1]', // name equals and prop differnce, then comparing it
prop: [{
A: { A: 1, B: 2 },
B: { A: 1, B: 2 },
C: { C: 78, D: 4, T: 7, }
}],
}, {
name: 'B [2]', // name equals, then skiping it
prop: [{
A: { A: 1, B: 2 },
B: { A: 1, B: 2 },
D: { C: 3, D: 4, Y: 13 }
}],
}, {
name: 'B [3]', // name equals and prop differnce, then comparing it
prop: [{
E: { A: 1, B: 2 },
R: { A: 1, B: 2 },
T: { C: 3, D: 4, }
}],
}, {
name: 'B [4]', // name and prop equals, then skiping it
prop: [{
A: { A: 1, B: 2 },
S: { A: 1, B: 2 },
D: { C: 3, D: 4, }
}],
}];
const p2 = [{
name: 'B [1]', // name equals and prop differnce, then comparing it
prop: [{
A: { A: 1, B: 8 },
B: { A: 1, B: 2 },
C: { C: 3, T: 7, O: 9 }
}],
}, {
name: 'B [6]', // name not equals, then skiping it
prop: [{
A: { A: 1, B: 2 },
B: { A: 1, B: 2 },
D: { C: 3, D: 4 }
}],
}, {
name: 'B [3]', // name equals and prop differnce, then comparing it
prop: [{
E: { A: 1, B: 2 },
R: { A: 1, B: 2, U: 150 },
T: { C: 3, D: 4, }
}],
}, {
name: 'B [4]', // name and prop equals, then skiping it
prop: [{
A: { A: 1, B: 2 },
S: { A: 1, B: 2 },
D: { C: 3, D: 4, }
}],
}];
const result = [{
name: 'B [1]',
propOne: [{
A: { B: 2 },
C: { C: 78, D: 4, O: 'Missing' }
}],
propTwo: [{
A: { B: 8 },
C: { C: 3, D: 'Missing', O: 9 }
}],
},{
name: 'B [3]',
propOne: [{
R: { U: 'Missing' }
}],
propTwo: [{
R: { U: 150 }
}]
}]
const diffDestructive = (a, b) => {
/**
* Copy the objects, remove all identical properties recursively,
* then add "Missing" properties for all properties from either side
* that doesn't exist on the other.
*/
const remove = (x, y) => {
for (let key of Object.keys(x)) {
// hasOwnProperty is only for the degenerate case { prop: undefined }
if (x[key] === y[key] && y.hasOwnProperty(key)) {
delete x[key];
delete y[key];
} // typeof null === "object", therefore an additional check is needed
else if (x[key] && typeof x[key] === "object" && y[key] && typeof y[key] === "object") {
remove(x[key], y[key]);
if ([x, y].every(e => Object.keys(e[key]).length === 0)) {
delete x[key];
delete y[key];
}
}
}
};
const addMissingNotes = (x, y) => {
for (let key of Object.keys(x)) {
if (!(y.hasOwnProperty(key))) y[key] = "Missing";
else if (x[key] && typeof x[key] === "object" && y[key] && typeof y[key] === "object")
addMissingNotes(x[key], y[key]);
}
};
// quick and dirty object deep-copy
let [modA, modB] = [a, b].map(e => JSON.parse(JSON.stringify(e)));
remove(modA, modB);
addMissingNotes(modA, modB);
addMissingNotes(modB, modA);
return [modA, modB];
};
const diffConstructive = (a, b) => {
/**
* Add differing properties to the result step by step.
* Nested objects are handled recursively.
*/
let diffA = {}, diffB = {};
for (let key of Object.keys(a)) {
//properties that a and b share
if (b.hasOwnProperty(key)) {
if (a[key] && typeof a[key] === "object" && b[key] && typeof b[key] === "object") {
let subDiffs = diffConstructive(a[key], b[key]);
// The way the construction works, Object.keys(subDiffs[0]).length !== 0 would be enough.
if (subDiffs.some(e => Object.keys(e).length !== 0)) {
[diffA[key], diffB[key]] = subDiffs;
}
} else if (a[key] !== b[key]) {
diffA[key] = a[key];
diffB[key] = b[key];
}
} // properties that a has but b doesn't
else {
diffA[key] = a[key];
diffB[key] = "Missing";
}
}
// properties that b has but a doesn't
for (let key of Object.keys(b)) {
if (!a.hasOwnProperty(key)) {
diffB[key] = b[key];
diffA[key] = "Missing";
}
}
return [diffA, diffB];
};
const compare = (a, b, method) => a
.map((e, i) => [e, b[i]])
//same name only
.filter(([a, b]) => a.name === b.name)
// formatting
.map(([a, b]) => {
const [diffA, diffB] = method(a.prop[0], b.prop[0]);
return {
name: a.name,
propOne: [diffA],
propTwo: [diffB]
};
})
// There must be a difference
.filter(e => [e.propOne[0], e.propTwo[0]].some(e => Object.keys(e).length !== 0));
const destructive = compare(p1, p2, diffDestructive);
const constructive = compare(p1, p2, diffConstructive);
console.log(`Constructive method gives the wanted result: ${_.isEqual(result, destructive)}`);
console.log(`Destructive method gives the wanted result: ${_.isEqual(result, constructive)}`);
<!--
this is only for a deepequals function, _.isEqual,
and only used for checking the results. I could have copied
one into the code, but why make this even longer...
-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.core.min.js"></script>

How to get some props of list array object by using reduce

I have list array object like:
let arr = [
{ a: 1, b: 2, c: 3, d: 4 },
{ a: 2, b: 3, c: 4, d: 5 },
{ a: 5, b: 6, c: 7, d: 8 }
]
and after using reduce()
// get props **b, c**
let arr_result = arr.reduce( ... )
// arr_result = [
// { b: 2, c: 3 },
// { b: 3, c: 4 },
// { b: 6, c: 7 }
// ]
use map.
let arr = [{
a: 1,
b: 2,
c: 3,
d: 4
},
{
a: 2,
b: 3,
c: 4,
d: 5
},
{
a: 5,
b: 6,
c: 7,
d: 8
}
]
const output = arr.map(({b, c}) => ({b, c}));
console.log(output);
You can use ES6(and beyond)'s object destructuring.
const arr = [
{ a: 1, b: 2, c: 3, d: 4 },
{ a: 2, b: 3, c: 4, d: 5 },
{ a: 5, b: 6, c: 7, d: 8 }
]
const res = arr.map(obj => {
const { b, c } = obj;
return { b, c };
});
console.log(res);
Since you asked to achieve this using reduce, here is the way. Pass an empty array as thisArg & inside reduce callback function create an object with required key and push it to the accumulator
let arr = [{
a: 1,
b: 2,
c: 3,
d: 4
},
{
a: 2,
b: 3,
c: 4,
d: 5
},
{
a: 5,
b: 6,
c: 7,
d: 8
}
];
let newArr = arr.reduce(function(acc, curr) {
acc.push({
b: curr.b,
c: curr.c
})
return acc;
}, [])
console.log(newArr)
If you want to use reduce:
const arr = [{a:1,b:2,c:3,d:4},{a:2,b:3,c:4,d:5},{a:5,b:6,c:7,d:8}];
const res = arr.reduce((a, { b, c }) => (a.push({ b, c }), a), []);
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: auto; }
It's honestly a lot easier with map:
const arr = [{a:1,b:2,c:3,d:4},{a:2,b:3,c:4,d:5},{a:5,b:6,c:7,d:8}];
const res = arr.map(({ b, c }) => ({ b, c }));
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: auto; }

Categories