If object set has an object property create an array - javascript

I have a response value which is dynamic which i need to store in redux state,
Response consist of array of object and and name
ex :
{data:[
{name:"abc",age:"10",id:"10"}
{name:"abc",age:"15",id:"20"}
{name:"def",age:"15",id:"20"}
]
name: "abc"
}
So if the name is same I need to create array with the name.
Expected :
abc:[
{name:"abc",age:"10",id:"10"}
{name:"abc",age:"15",id:"20"}
]
something I tried
data.map(function(o) {
if(data.name ==o.name)
return name[o];
});

If you're wanting a new object with a key of the name property you could try something like this
const response = {
data: [{
name: "abc",
age: "10",
id: "10"
},
{
name: "abc",
age: "15",
id: "20"
},
{
name: "def",
age: "15",
id: "20"
},
],
name: "abc"
}
const createSet = (someData) => {
let key = someData.name
let data = someData.data.filter(e => e.name === key)
return {
[key]: data
}
}
console.log(createSet(response))

You can extract duplicated using reduce and filter :
var data = {
data:[
{name:"abc",age:"10",id:"10"},
{name:"abc",age:"15",id:"20"},
{name:"def",age:"15",id:"20"}
],
name: "abc"
}
const lookup = data.data.reduce((a, e) => {
a[e.name] = ++a[e.name] || 0;
return a;
}, {});
console.log(data.data.filter(e => lookup[e.name]));

Related

want to display all maximum 'levelNumber' of objects in an array

arr1 = [
{
"levelNumber": "2",
"name": "abc",
},
{
"levelNumber": "3",
"name": "abc"
},
{
"levelNumber": "3",
"name": "raks",
}
]
my result array should have objects with max levelNumber i.e 3 in this case.
it should look like:
resultArr = [
{
"levelNumber": "3",
"name": "abc"
},
{
"levelNumber": "3",
"name": "raks",
}
]
note that here levelNumber can be anything..
please help me with the generic nodejs code to get duplicate max value objects
You can first find the max level of all the objects in the array and then filter the array
arr1 = [
{
"levelNumber": "2",
"name": "abc",
},
{
"levelNumber": "3",
"name": "abc"
},
{
"levelNumber": "3",
"name": "raks",
}
]
const maxLevel = String(Math.max(...arr1.map(obj => Number(obj.levelNumber))))
const maxLevelObjects = arr1.filter(obj => obj.levelNumber === maxLevel)
console.log(maxLevelObjects);
const data = [
{
"levelNumber": "2",
"name": "abc",
},
{
"levelNumber": "3",
"name": "abc"
},
{
"levelNumber": "3",
"name": "raks",
}
];
const levelNumbers = data.map((item) => parseInt(item.levelNumber));
const maxLevelNumber = Math.max(...levelNumbers).toString();
const highestLevelItems = data.filter((item) => item.levelNumber == maxLevelNumber);
console.log(highestLevelItems);
/* output
[
{ levelNumber: '3', name: 'abc' },
{ levelNumber: '3', name: 'raks' }
]
*/
EDIT
As #nat mentioned in comment:
if I add one more object in the array, with name = 'raks & levelNumber = '4' then it should display maximum levelNumber wrt that particular name. i.e.
{ "levelNumber": "3", "name": "abc" }, { "levelNumber": "4", "name": "raks" }
To achieve this, you have to:
make a Set of names
make a separate empty array to hold final result
repeat the above process for each name and add result in the array
return complete result
const data = [
{
"levelNumber": "2",
"name": "abc",
},
{
"levelNumber": "3",
"name": "abc"
},
{
"levelNumber": "3",
"name": "raks",
},
{
"levelNumber": "4",
"name": "raks",
},
{
"levelNumber": "5",
"name": "raks",
}
];
// 1.
const names = new Set(data.map((item) => item.name)); // Set is used to get only unique items
// 2.
const result = []; // For normal JS
// const result: Array<{levelNumber: string, name: string}> = []; // For TS
// 3.
names.forEach((name) => {
/* minify data (filter items with only particular name) e.g. [{levelNumber: '2', name: 'abc'}, {levelNumber: '3', name: 'abc'}] */
const minifiedData = data.filter((item) => item.name === name);
/* same process, now for minified array */
const levelNumbers = minifiedData.map((item) => parseInt(item.levelNumber));
const maxLevelNumber = Math.max(...levelNumbers).toString();
minifiedData.forEach((item) => {
if (item.levelNumber == maxLevelNumber)
result.push(item); // push every matching item (item with highest level) in final result
});
});
// 4.
console.log(result);
const arr1 = [
{
levelNumber: '2',
name: 'abc',
},
{
levelNumber: '3',
name: 'abc',
},
{
levelNumber: '3',
name: 'raks',
},
];
const getHighLevelElements = (array) => {
if (array.length === 0) return null;
array.sort((elem1, elem2) => {
if (Number(elem1.levelNumber) < Number(elem2.levelNumber)) {
return 1;
}
if (Number(elem1.levelNumber) > Number(elem2.levelNumber)) {
return -1;
}
return 0;
});
return array.filter((elem) => elem.levelNumber === array[0].levelNumber);
};
const resultArr = getHighLevelElements([...arr1]);
console.log(resultArr);
I would first have a variable called highestLevel to store the highest level number found in the array of objects (will be used later while looping), loop through the whole array and checking every key levelNumber and storing that number IF highestLevel is lower than the value of the current object levelNumber.
After I've looped through the array and got the actual highestLevel number, I would loop through again and only get the objects that are equivalent to my variable highestLevel
You can just iterate one time over arr1 with Array.prototype.reduce()
Code:
const arr1 = [{levelNumber: '2',name: 'abc',},{levelNumber: '3',name: 'abc',},{levelNumber: '3',name: 'raks'}]
const result = arr1.reduce((a, c) => !a.length || +c.levelNumber === +a[0].levelNumber
? [...a, c]
: +c.levelNumber > +a[0].levelNumber
? [c]
: a,
[])
console.log(result)

JavaScript modify Array of Objects and alter contained data

I am having difficulties formatting some data. Currently, I receive data in the following structure.
[
{
"q1":"5",
"q2":[
"13",
"12",
],
"q3":"test",
}
]
I essentially need to modify this or even create a new object, that takes the following structure.
[
{
id: 1, //q1
answers: [
{
answer: '5',
},
],
},
{
id: 2, //q2
answers: [
{
answer: '13',
},
{
answer: '12',
},
],
},
{
id: 3, //q3
answers: [
{
answer: 'test',
},
],
},
];
So the id in the above would be obtained by remove the q and getting the number in the first data object. It would then have an answers array that would have an object for each answer.
I have been attempting this but have gotten lost. I don't know if I should use loops, mapping, filters etc. To be honest, the furthest I have got so far is obtaining the keys
var modified = data.map(function(item) {
return Object.keys(item)
})
I have created a JSFiddle where I have been attempting to do this.
Is there any way I can achieve the data I am after?
Many thanks
Please use map function.
const data = {
"q1":"5",
"q2":[
"13",
"12",
],
"q3":"test",
};
const result = Object.keys(data).map(key => {
let item = {id: key.substring(1), answers: []};
if(typeof data[key] === "string")
item.answers.push({answer: data[key]});
else
item.answers = data[key].map(val => ({answer: val}));
return item;
});
console.log(result)
const inputData = [
{
"q1":"5",
"q2":[
"13",
"12",
],
"q3":"test",
}
]
function answerMapper(objVal, id){
return Array.isArray(objVal)
?
{ id, answers: objVal.map(answer => ({ answer }))}
:
{ id, answers: [{answer: objVal }] }
}
function formatObject(obj){
return Object.keys(obj).map((k, i) => answerMapper(obj[k], i+1));
}
const result = inputData.map(obj => formatObject(obj));
// remove flatMap if your inputData has more than one entry
console.log(result.flatMap(x => x));
map over the first element of the data with Object.entries, grab the key and value, create a new answers array and return a new object.
const data = [{
"q1": "5",
"q2": [
"13",
"12",
],
"q3": "test",
}];
const out = Object.entries(data[0]).map(obj => {
const [ key, value ] = obj;
const id = Number(key[1]);
// If the the value is an array
// return a new array of mapped data
// Otherwise return an array containing
// one object
const answers = Array.isArray(value)
? value.map(el => ({ answer: el }))
: [{ answer: value }];
// Return the new object
return { id, answers };
});
console.log(out);
lets create a pure function which accepts the object in the array like so
const processObject = obj => Object.keys(obj).map(id => {
const answer = obj[id];
const answers = Array.isArray(answer) ? answer : [answer]
const answerObjectArray = answers.map(ans => ({
answer: ans
}));
return {
id: +id.substring(1),
answers: answerObjectArray
}
});
const dataArray = [{
"q1": "5",
"q2": [
"13",
"12",
],
"q3": "test",
}];
const output = processObject(dataArray[0]);
console.log(output);

Change particular key in nested array to object in javascript

If the fields key in a object is array, change the first value of arrays as a key value pair object in javascript.
var obj =
[
{ id:1, fields:["item", "2", "list"]},
{ id:2, fields:["sample", "1", "check"]}
]
function newObj(obj) {
let objFields = {};
modifiedObj.fields.forEach(field => objFields[field] = field);
modifiedObj.fields= objFields;
return modifiedObj;
}
var result = this.newObject(obj)
Expected Output
{
item: "item",
sample: "sample"
}
Try this:
var obj =
[
{ id:1, fields:["item", "2", "list"]},
{ id:2, fields:["sample", "1", "check"]}
]
function newObject(obj) {
let objFields = {};
obj.forEach(e => {
if(e.fields && e.fields.length>0)
objFields[e.fields[0]] = e.fields[0];
});
return objFields;
}
var result = this.newObject(obj);
console.log(result);
Here is a functional approach that makes use of Object.assign(), spread operator, and Array.map() to create the object you need.
const input = [
{ id: 1, fields: ["item", "2", "list"] },
{ id: 2, fields: ["sample", "1", "check"] }
];
const process = (input) => (Object.assign(...input.map(({ fields }) => (
fields.length ? { [fields[0]]: fields[0] } : {}
))));
console.log(process(input));
Your snippet was close, you just needed to clean up the variable names, and then using map makes it a bit neater too:
const obj = [
{id: 1, fields: ["item", "2", "list"]},
{id: 2, fields: ["sample", "1", "check"]}
]
function newObj(inputArray) {
let outputObject = {};
inputArray.map(item => item.fields[0])
.forEach(field => outputObject[field] = field);
return outputObject;
}
var result = newObj(obj)
console.log(result)

How to code 'ID of DOM method to using in recursion'?

I have a problem in 'getObjectById to using in recursion'. Executing the function getObject(data, '11') ---> undefined. I don't know why this happens: undefined.
In function getObject(data, '1'~'9') ---> I got the solved. But '11' ,'12', '13', '14' ---> undefined
For solving this problem, I have to use forEach, Array.prototype.apply, but I cannot solve it.
Using filter ---> TypeError: Cannot read property 'filter' of undefined
Using length ---> TypeError: Cannot read property 'length' of undefined
In first under line, I have got the problem to solve. In second under line, I wrote the code to solve this problem. As I think that I explain my logic to solving the problem. But, in test case, it is failed.
The solution to this problem is:
let output = getObjectById(TREE_DATA.items, '1'))
console.log(output) --> { "id": "1", "name": "johnny" }
--in first under line,
let TREE_DATA = {
items: [
{
id: "1",
name: "johnny"
},
{
id: "2",
name: "ingi",
children: [
{
id: "3",
name: "johnson"
},
{
id: "4",
name: "katy"
},
{
id: "5",
name: "steve",
children: [
{
id: "6",
name: "lisa"
},
{
id: "7",
name: "penny",
children: [
{
id: "8",
name: "john"
},
{
id: "9",
name: "hoyong"
}
]
},
{
id: "10"
}
]
},
{
id: "11"
},
{
id: "12"
}
]
},
{
id: "13"
},
{
id: "14"
}
]
};
--in second under line,
function getObject(json, id) {
let test = json.items;
let newA = [];
function getA(a, id) {
a.filter(function(e) {
console.log("this is : ", e);
if (e.id && e.id === id) {
return newA.push(e);
} else if (e.id !== id && e.children) {
return getA(e.children, id);
}
});
}
getA(test, id);
return newA[0];
}
Because your input data is a recursive structure, a program with a recursive structure will be the best match. In this case you have -
a list of nodes (TREE_DATA.items)
where each node (object) may contain a children property, which is also a list of nodes
This recursive relationship gives us a unique opportunity to learn about special kind of recursion where one function, A, calls function B, which in turn calls function A, which calls B, and so on... this is called mutual recursion.
We start with a function that takes just one of the input nodes, aptly named find1. It accepts a single node, destructured to children and o, and an id to search for, id -
const find1 = ({ children = [], ...o }, id = 0) =>
o.id == id // if the object's id matches the input id,
? o // match found! return the object
: findAll(children, id) // otherwise findAll of the children with the id
Next it's obvious we need to implement findAll. It accepts a list of nodes, destructured to first and more, and an id to search for, id -
const findAll = ([ first, ...more ], id = 0) =>
first === undefined // if the list is empty,
? undefined // there's nothing to search! return no match
: find1(first, id) // find1 the first item in the list using the id
|| findAll(more, id) // OR findAll on more using the same id
That's it! The functions almost writes themselves with no need for extraneous variables or steps. It behaves exactly like we expect -
console.log(findAll(TREE_DATA.items, 1))
// { id: "1", name: "johnny" }
console.log(findAll(TREE_DATA.items, 11))
// { id: "11" }
console.log(findAll(TREE_DATA.items, 99))
// undefined (no match found)
Verify the results in your own browser by running the snippet below -
const find1 = ({ children = [], ...o }, id = 0) =>
o.id == id
? o
: findAll(children, id)
const findAll = ([ first, ...more ], id = 0) =>
first === undefined
? undefined
: find1(first, id) || findAll(more, id)
const TREE_DATA =
{items:[{id:"1",name:"johnny"},{id:"2",name:"ingi",children:[{id:"3",name:"johnson"},{id:"4",name:"katy"},{id:"5",name:"steve",children:[{id:"6",name:"lisa"},{id:"7",name:"penny",children:[{id:"8",name:"john"},{id:"9",name:"hoyong"}]},{id:"10"}]},{id:"11"},{id:"12"}]},{id:"13"},{id:"14"}]}
console.log(findAll(TREE_DATA.items, 1))
// { id: "1", name: "johnny" }
console.log(findAll(TREE_DATA.items, 11))
// { id: "11" }
console.log(findAll(TREE_DATA.items, 99))
// undefined (no match found)
Is this what you are looking for?
let TREE_DATA = {
items: [
{
id: "1",
name: "johnny"
},
{
id: "2",
name: "ingi",
children: [
{
id: "3",
name: "johnson"
},
{
id: "4",
name: "katy"
},
{
id: "5",
name: "steve",
children: [
{
id: "6",
name: "lisa"
},
{
id: "7",
name: "penny",
children: [
{
id: "8",
name: "john"
},
{
id: "9",
name: "hoyong"
}
]
},
{
id: "10"
}
]
},
{
id: "11"
},
{
id: "12"
}
]
},
{
id: "13"
},
{
id: "14"
}
]
};
function getObject(json, id) {
let test = json.items;
let newA = [];
function getA(a, id) {
a &&
a.forEach(function(e) {
if (e.id === id) {
newA.push(e);
} else if (e.children) {
getA(e.children, id);
}
});
}
getA(test, id);
return newA[0];
}
function getObjectById(items, key) {
let ret = {};
for (let item of items) {
if (item.id === key) {
return item;
}
if (item.children) {
let innerRet = getObjectById(item.children, key);
if (Object.keys(innerRet).length) return innerRet;
}
}
return ret;
}
console.log("2", getObjectById(TREE_DATA.items, "2"));
console.log("3", getObjectById(TREE_DATA.items, "3"));
console.log("11", getObjectById(TREE_DATA.items, "11"));
console.log("12", getObjectById(TREE_DATA.items, "12"));
console.log("13", getObjectById(TREE_DATA.items, "13"));
console.log("2", getObject(TREE_DATA, "2"));
console.log("3", getObject(TREE_DATA, "3"));
console.log("11", getObject(TREE_DATA, "11"));
console.log("12", getObject(TREE_DATA, "12"));
console.log("13", getObject(TREE_DATA, "13"));
Edit: debugged and added your function as well.

Relate and merge array of same Department

I am working on an application where I need to get combine the object of same department based on the
conditions provided in the second Array and attach the relation to the object.
let inArr1 = [{"D1D2":"AND"},{"D3D4":"OR"}]
let inArr2 =[{"ID":"1","NAME":"KEN","DEPT1":"CSE"},
{"ID":"2","NAME":"MARK","DEPT2":"IT"},
{"ID":"3","NAME":"TOM","DEPT3":"ECE"},
{"ID":"4","NAME":"SHIV","DEPT4":"LIB"},
{"ID":"5","NAME":"TIM","DEPT5":"SEC"}
]
Output
outArr ={
[{"ID":"1","NAME":"KEN","DEPT1":"CSE","REL":"AND"},
{"ID":"2","NAME":"MARK","DEPT2":"IT","REL":"AND"}], //Arr1
[{"ID":"3","NAME":"TOM","DEPT3":"ECE","REL":"OR"},
{"ID":"4","NAME":"SHIV","DEPT4":"LIB","REL":"OR"}], //Arr2
[{"ID":"5","NAME":"TIM","DEPT5":"SEC"}] //Arr3
}
Code:
let condArr=[],outArr,i=1;
inArr1.forEach(condt => {
let dept = Object.keys(condt)[0];
let tmparr = dept.split("D");
tmparr.shift()
condArr.push(tmparr)
});
inArr2.forEach(condt => {
if(condArr.includes(inArr2.D+i)){
i++;
outArr.push(inArr2);
}
});
Your code has a bit confused logic, i would suggest rather this
let inArr1 = [{"D1D2":"AND"},{"D3D4":"OR"},{"D5D6":"AND"}]
let inArr2 =[{"ID":"1","NAME":"KEN","DEPT1":"CSE"},
{"ID":"2","NAME":"MARK","DEPT2":"IT"},
{"ID":"3","NAME":"TOM","DEPT3":"ECE"},
{"ID":"4","NAME":"SHIV","DEPT4":"LIB"},
{"ID":"5","NAME":"TIM","DEPT5":"SEC"},
{"ID":"6","NAME":"TLA","DEPT6":"SEC"},
]
// first lets create object of ids as keys and conditions as values
const [keys, conditions] = inArr1.reduce((agg, cond, index) => {
Object.entries(cond).forEach(([key, value]) => {
key.split('D').forEach(v => { if (v) agg[0][v] = { value, index }})
agg[1].push([])
})
return agg
}, [{}, []]) // {1: "AND", 2: "AND", 3: "OR", 4: "OR"}
conditions.push([])
// and now just map over all elements and add condition if we found id from the keys
inArr2.forEach(item => {
const cond = keys[item.ID]
if (cond) conditions[cond.index].push({...item, REL: cond.value})
else conditions[conditions.length - 1].push(item)
})
const res = conditions.filter(v => v.length)
console.log(res)
You could store the goups by using the ID and use new objects.
let inArr1 = [{ D1D2: "AND" }, { D3D4: "OR" }],
inArr2 = [{ ID: "1", NAME: "KEN", DEPT1: "CSE" }, { ID: "2", NAME: "MARK", DEPT2: "IT" }, { ID: "3", NAME: "TOM", DEPT3: "ECE" }, { ID: "4", NAME: "SHIV", DEPT4: "LIB" }, { ID: "5", NAME: "TIM", DEPT5: "SEC" }],
groups = inArr1.reduce((r, o) => {
Object.entries(o).forEach(([k, REL]) => {
var object = { REL, group: [] };
k.match(/[^D]+/g).forEach(id => r[id] = object);
});
return r;
}, {}),
grouped = inArr2.reduce((r, o) => {
var { REL, group } = groups[o.ID] || {};
if (group) {
if (!group.length) r.push(group);
group.push(Object.assign({}, o, { REL }));
} else {
r.push([o]);
}
return r;
}, []);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
can try other solution:
let inArr1 = [{ D1D2: "AND" }, { D3D4: "OR" }, { D6D7: "XOR" }];
let inArr2 = [
{ ID: "1", NAME: "KEN", DEPT1: "CSE" },
{ ID: "2", NAME: "MARK", DEPT2: "IT" },
{ ID: "3", NAME: "TOM", DEPT3: "ECE" },
{ ID: "4", NAME: "SHIV", DEPT4: "LIB" },
{ ID: "5", NAME: "TIM", DEPT5: "SEC" },
{ ID: "9", NAME: "BAR", DEPT5: "XYZ" },
{ ID: "6", NAME: "FOO", DEPT5: "XYZ" },
];
let unmatchedArr = []
let matchedArr = inArr2.reduce((acc, obj) => {
// getting index matched from inArr1 objects key
const indexMatched = getIndexMatch(obj.ID);
// creating index if not exists
if (!acc[indexMatched] && indexMatched !== null) acc[indexMatched] = [];
// if some index matched it merge current obj with DEL property with inArr1[indexMatched] key => value
return indexMatched !== null
? acc[indexMatched].push({
...obj,
DEL: inArr1[indexMatched][Object.keys(inArr1[indexMatched])[0]]
})
// pushing on unmatchedArr
: unmatchedArr.push(obj)
, acc
}, []);
function getIndexMatch(id) {
for (const [index, obj] of inArr1.entries()) {
for (const key of Object.keys(obj)) {
// spliting only digits of the current key of object
if (key.match(/\d/g).includes(id)) return index; // returning index of inArr1 if is included
}
}
return null;
}
// merging arrays
const result = [...matchedArr, unmatchedArr];
console.log(result);

Categories

Resources