jquery update property in an array from another array - javascript

I want to update a property in an array from another array by matching a field by using jquery.
objArray = [ { Id: 1, Val: 'A'}, { Id: 3, Val: 'B'}, { Id: 5, Val: 'C'} ];
After doing some processing, I am getting an array like this.
objnewArray = [ { Id: 1, Value: 'AA'}, { Id: 3, Value: 'BB'}, { Id: 5, Value: 'CC'} ];
Now I want to update objArray Val field to objnewArray's value field so the result is like this
objArray = [ { Id: 1, Val: 'AA'}, { Id: 3, Val: 'BB'}, { Id: 5, Val: 'CC'} ];
Is there any other way other than looping both the arrays ,matching the Id and updating the Val property?

You could use a hash table and loop the target first and the the new object for assigning to the old object.
var objArray = [{ Id: 1, Val: 'A' }, { Id: 3, Val: 'B' }, { Id: 5, Val: 'C' }],
objnewArray = [{ Id: 1, Value: 'AA', extra: 42 }, { Id: 3, Value: 'BB' }, { Id: 5, Value: 'CC' }],
hash = Object.create(null);
objArray.forEach(function (a) {
hash[a.id] = a;
});
objnewArray.forEach(function (a) {
Object.keys(a).forEach(function (k) {
hash[a.id][k] = a[k];
});
});
console.log(objnewArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES6 with Map
var objArray = [{ Id: 1, Val: 'A' }, { Id: 3, Val: 'B' }, { Id: 5, Val: 'C' }],
objnewArray = [{ Id: 1, Value: 'AA', extra: 42 }, { Id: 3, Value: 'BB' }, { Id: 5, Value: 'CC' }],
hash = new Map;
objArray.forEach(a => hash.set(a.id, a));
objnewArray.forEach(a => Object.keys(a).forEach(k => hash.get(a.id)[k] = a[k]));
console.log(objnewArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES6 with Array#find
var objArray = [{ Id: 1, Val: 'A' }, { Id: 3, Val: 'B' }, { Id: 5, Val: 'C' }],
objnewArray = [{ Id: 1, Value: 'AA', extra: 42 }, { Id: 3, Value: 'BB' }, { Id: 5, Value: 'CC' }];
objnewArray.forEach(a =>
Object.keys(a).forEach(k => objArray.find(b => a.id === b.id)[k] = a[k]));
console.log(objnewArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Traverse the array, create new key and assign its value properly, delete the old key. You are done.
objnewArray = [ { Id: 1, Value: 'AA'}, { Id: 3, Value: 'BB'}, { Id: 5, Value: 'CC'} ];
var objArray = objnewArray.map(function(el){
el.Val = el.Value; // Create new key Val
delete el.Value; // Delete old key Value
return el;
});
console.log(objArray);

You can use Array.prototype.reduce with a hash table and Object.assign to create a shallow object copy to get the required output array - see demo below:
var objArray = [ { Id: 1, Val: 'A'}, { Id: 3, Val: 'B'}, { Id: 5, Val: 'C'} ];
var objnewArray = [ { Id: 1, Value: 'AA'}, { Id: 3, Value: 'BB'}, { Id: 5, Value: 'CC'}];
var result = objArray.reduce(function(hash){
//create hash table
objnewArray.forEach(function(element){
hash[element.Id]=element.Value;
});
// reduce to the required result
return function(prev, curr){
var element = Object.assign({}, curr);
element.Val = hash[curr.Id];
prev.push(element);
return prev;
}
}(Object.create(null)),[]);
console.log(result);
.as-console-wrapper{top:0;max-height:100%!important;}

You can iterate over objArray and $.extend the object
Jquery -
objArray = [ { Id: 1, Value: 'A'}, { Id: 3, Value: 'B'}, { Id: 5, Value: 'C'} ];
objnewArray = [ { Id: 1, Value: 'AA'}, { Id: 3, Value: 'BB'}, { Id: 5, Value: 'CC'} ];
objArrayById = [];
objArray.forEach(function(value){
objArrayById[value.Id] = value;
});
objnewArray.forEach(function(value,index){
objArrayById[value.Id] = $.extend(objArrayById[value.Id],value);
});
console.log(objArrayById);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
ES6
objArray = [ { Id: 1, Value: 'A'}, { Id: 3, Value: 'B'}, { Id: 5, Value: 'C'} ];
objnewArray = [ { Id: 1, Value: 'AA'}, { Id: 3, Value: 'BB'}, { Id: 5, Value: 'CC'} ];
objArrayById = [];
objArray.forEach(function(value){
objArrayById[value.Id] = value;
});
objnewArray.forEach(function(value){
objArrayById[value.Id] = Object.assign(objArrayById[value.Id],value);
});
console.log(objArrayById);

This is quite similar to #void answer
Iterating through objArray so not to update the objnewArray object
var objnewArray = [ { Id: 1, Value: 'AA'}, { Id: 3, Value: 'BB'}, { Id: 5, Value: 'CC'} ];
var objArray = JSON.parse(JSON.stringify(objnewArray));
//console.log(objArray)
objArray = objArray.map(function(doc){
doc.Val = doc.Value;
delete doc.Value;
return doc;
});
console.log(objArray)

Related

How to count the no of occurences of a certain key in an array of object & append the count to each key's value

How to count the no of occurences of the 'value' key in a object inside an array & append the count to each value if any.
Here 'a' is the source data
var a = [
{ id: 1, value: "10000"},
{ id: 2, value: "20000"},
{ id: 3, value: "30000"},
{ id: 4, value: "10000"},
{ id: 5, value: "20000"},
{ id: 6, value: "40000"},
{ id: 7, value: "10000"},
{ id: 8, value: "70000"}
]
What i want to achieve is as following
result = [
{ id: 1, value: "10000"},
{ id: 2, value: "20000"},
{ id: 3, value: "30000"},
{ id: 4, value: "10000 (1)"},
{ id: 5, value: "20000 (1)"},
{ id: 6, value: "40000"},
{ id: 7, value: "10000 (2)"},
{ id: 8, value: "10000 (3)"}
]
You can use Array.map and save the value
I think this is more readable than using Map
const values = {},
b = a.map(({ id, value }) => {
values[value] = (values[value] || 0) + 1; // assign and/or increment
if (values[value] > 1) value += ` (${values[value]-1})`;
return { id, value };
});
console.log(b)
<script>
var a = [
{ id: 1, value: "10000"},
{ id: 2, value: "20000"},
{ id: 3, value: "30000"},
{ id: 4, value: "10000"},
{ id: 5, value: "20000"},
{ id: 6, value: "40000"},
{ id: 7, value: "10000"},
{ id: 8, value: "10000"}
]</script>
You can make use of Map as a place where you can store count of number of occurence.
const a = [
{ id: 1, value: '10000' },
{ id: 2, value: '20000' },
{ id: 3, value: '30000' },
{ id: 4, value: '10000' },
{ id: 5, value: '20000' },
{ id: 6, value: '40000' },
{ id: 7, value: '10000' },
{ id: 8, value: '70000' },
];
const map = new Map();
const result = a.map((o) => {
const valueInMap = map.get(o.value);
map.set(o.value, (valueInMap ?? 0) + 1);
return valueInMap ? { ...o, value: `${o.value} (${valueInMap})` } : o;
});
console.log(result);
var a = [
{ id: 1, value: '10000' },
{ id: 2, value: '20000' },
{ id: 3, value: '30000' },
{ id: 4, value: '10000' },
{ id: 5, value: '20000' },
{ id: 6, value: '40000' },
{ id: 7, value: '10000' },
{ id: 8, value: '10000' },
];
const hashMap = {};
const newArr = a.map((el) => {
const temp = { ...el };
if (!hashMap[el.value]) {
hashMap[el.value] = 1;
} else if (hashMap[el.value]) {
temp.value = `${el.value} (${hashMap[el.value]})`;
hashMap[el.value] += 1;
}
return temp;
});
console.log(newArr);

Javascript - How to filter custom repetitive objects from array [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Based on an objects array like this. I want to filter repetitive objects key, in order to affect some repetitive keys but not everyone.
var arr = [
{id: 1, value: 'John'},
{id: 2, value: 'John'}, // Should be filtered
{id: 3, value: 'John'}, // Should be filtered
{id: 4, value: 'John'}, // Should be filtered
{id: 5, value: 'Alex'},
{id: 6, value: 'Louis'},
{id: 7, value: 'David'},
{id: 8, value: 'David'}, // Should not be filtered
]
Result:
arr = [
{id: 1, value: 'John'},
{id: 5, value: 'Alex'},
{id: 6, value: 'Louis'},
{id: 7, value: 'David'},
{id: 8, value: 'David'},
]
I tried this at the moment:
arr = arr.reduce((a, b) => {
if (!a.some(x => x.description === b.description)) a.push(b);
return a;
}, []);
Thanks is advance.
If you like to filter duplicates and keep the first object, you could take a closure over a Set for filtering.
const
array = [{ id: 1, value: 'John' }, { id: 2, value: 'John' }, { id: 3, value: 'John' }, { id: 4, value: 'John' }, { id: 5, value: 'Alex' }, { id: 6, value: 'Louis' }, { id: 7, value: 'David' }, { id: 8, value: 'David' }],
keep = ['David'],
result = array.filter(
(s => ({ value }) => keep.includes(value) || !s.has(value) && s.add(value))
(new Set)
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Just uising Set data structure, and some array or set with exceptions.
var arr = [
{id: 1, value: 'John'},
{id: 2, value: 'John'}, // Should be filtered
{id: 3, value: 'John'}, // Should be filtered
{id: 4, value: 'John'}, // Should be filtered
{id: 5, value: 'Alex'},
{id: 6, value: 'Louis'},
{id: 7, value: 'David'},
{id: 8, value: 'David'}, // Should not be filtered
]
const filterDuplicates = (arr, exceptions) => {
const values = new Set();
return arr.filter(item => {
if(values.has(item.value) && !exceptions.includes(item.value)){
return false;
} else {
values.add(item.value);
return true;
}
})
}
console.log(filterDuplicates(arr, ["David"]));
You can use Array#filter with a boolean flag to store whether or not the value has already appeared.
var arr = [
{id: 1, value: 'John'},
{id: 2, value: 'John'}, // Should be filtered
{id: 3, value: 'John'}, // Should be filtered
{id: 4, value: 'John'}, // Should be filtered
{id: 5, value: 'Alex'},
{id: 6, value: 'Louis'},
{id: 7, value: 'David'},
{id: 8, value: 'David'}, // Should not be filtered
];
const removeRepeats = (arr, val)=>{
let found = false;
return arr.filter(({value})=>value !== val || (!found && (found = true)));
};
console.log(removeRepeats(arr, 'John'));
var arr = [
{ id: 1, value: "John" },
{ id: 2, value: "John" }, // Should be filtered
{ id: 3, value: "John" }, // Should be filtered
{ id: 4, value: "John" }, // Should be filtered
{ id: 5, value: "Alex" },
{ id: 6, value: "Louis" },
{ id: 7, value: "David" },
{ id: 8, value: "David" }, // Should not be filtered
];
const filtered = Array.from(
arr
.reduce((filtered, item) => {
if (!filtered.has(item.value)) {
filtered.set(item.value, item);
}
return filtered;
}, new Map())
.values()
);
console.log(filtered);

filter an array of object with same id

Let's say i have a json like this:
[
{
id: 3,
name: 'A',
depth:0
},
{
id: 2,
name: 'C'
depth:1
},
{
id: 3,
name: 'B',
depth:1
},
{
id: 1,
name: 'Z'
},
{
id: 2,
name: 'F',
depth:0
}
]
what i want to do is to create another array of object with these rules:
1: find the same ids in array
2: check the depth (so if depth was 0 it should be the parent and if depth was 1 it should be the child of element with depth 0)
like this :
[
{
id: 3,
name: 'A',
depth:0,
child:[
{
id: 3,
name: 'B',
depth:1
},
]
},
{
id: 1,
name: 'Z'
},
{
id: 2,
name: 'F',
depth:0,
child:[
{
id: 2,
name: 'C',
depth:1,
},
]
}
]
Any help would be appreciated it ?
Here you go..
var a = [
{
id: 3,
name: 'A',
depth:0
},
{
id: 2,
name: 'C',
depth:1
},
{
id: 3,
name: 'B',
depth:1
},
{
id: 1,
name: 'Z'
},
{
id: 2,
name: 'F',
depth:0
}]
var c = a.filter(a => a.depth == 0);
var zeroDepth = a.filter(a => a.depth === undefined);
zeroDepth.forEach(z => c.push(z));
a.forEach(a =>
{
if(a.depth == 1){
c.forEach(c =>
{
if(c.id == a.id){
c.child = [];
c.child.push(a);
}
})
}
})
console.log(c);

Ramda on arrays in javascript

var censusMembers = Object.freeze([
{
id: 1,
name: 'Bob'
}, {
id: 2,
name: 'Sue'
}, {
id: 3,
name: 'Mary',
household_id: 2
}, {
id: 4,
name: 'Elizabeth',
household_id: 6
}, {
id: 5,
name: 'Tom'
}, {
id: 6,
name: 'Jill'
}, {
id: 7,
name: 'John',
household_id: 6
}
]);
This is my array
I want to count the number of elements which has household id using ramda function ?
how can i do that ?
You can also use R.countBy to count all items that have/don't have household_id using R.has(), and than get the count for true using R.prop():
const { pipe, countBy, has, prop } = R;
const censusMembers = Object.freeze([{"id":1,"name":"Bob"},{"id":2,"name":"Sue"},{"id":3,"name":"Mary","household_id":2},{"id":4,"name":"Elizabeth","household_id":6},{"id":5,"name":"Tom"},{"id":6,"name":"Jill"},{"id":7,"name":"John","household_id":6}]);
const countHouseholders = pipe(
countBy(has('household_id')),
prop('true'),
);
const result = countHouseholders(censusMembers);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
has looks to be what you're missing:
var censusMembers = Object.freeze([
{id: 1, name: 'Bob'},
{id: 2, name: 'Sue' },
{id: 3, name: 'Mary', household_id: 2 },
{id: 4, name: 'Elizabeth', household_id: 6},
{id: 5, name: 'Tom'},
{id: 6, name: 'Jill'},
{id: 7, name: 'John', household_id: 6}
]);
const countHouseholders = R.pipe(R.filter(R.has('household_id')), R.length)
console.log(countHouseholders(censusMembers))
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
Don't use the function filter to count stuff because you're creating an array only to get the length.
You can use the function R.reduce and within the handler, check for the key household_id
var censusMembers = Object.freeze([{id: 1,name: 'Bob'}, {id: 2,name: 'Sue'}, {id: 3,name: 'Mary',household_id: 2}, {id: 4,name: 'Elizabeth',household_id: 6}, {id: 5,name: 'Tom'}, {id: 6,name: 'Jill'}, {id: 7,name: 'John',household_id: 6}]);
// With household_id
// (true is coerced to 1) = 1
console.log("With:", R.reduce((a, c) => ('household_id' in c) + a, 0, censusMembers));
// Without household_id
// !(false is coerced to 0) = 1
console.log("Without:", R.reduce((a, c) => !('household_id' in c) + a, 0, censusMembers));
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

How to create a tree of existing json

I want to parse a json that is fetch from api
I have following schema
nodes = [
{
id: 1,
name: 'root1',
key: 'value1'
key1: 'value2'
children: [
{ id: 2, name: 'child1' },
{ id: 3, name: 'child2' }
]
},
{
id: 4,
name: 'root2',
key3: 'value3'
key4: 'value4'
children: [
{ id: 5, name: 'child2.1' },
{
id: 6,
name: 'child2.2',
key5: 'value5'
key6: 'value6'
children: [{
id: 7,
name: 'subsub',
children: [{
id: 8,
name: 'subsubsub'
}]
}]
}
]
}
];
I'm trying following but not working
data = []
var nodesFun = function(n, data, cObj) {
let obj = {}
obj["name"] = n['name']
if (n['children']) {
console.log(obj);
console.log("name--> "+n['name']);
let childList = []
for (let i=0; i < n['children'].length; i++){
console.log("cname--> "+n['children'][i]['name']);
childList.push({"name": n['children'][i]['name']})
let dataObj = nodesFun(n['children'][i], data, obj)
if (dataObj){
data.push(dataObj)
}
}
obj["children"] = childList
cObj["children"] = obj
return cObj
}else{
cObj["children"] = obj
return cObj
}
}
nodesFun(nodes, data, {})
console.log(nodes);
Now I want to convert above json in following format using recursive function
nodes = [{
id: 1,
name: 'root1',
children: [
{ id: 2, name: 'child1' },
{ id: 3, name: 'child2' }
]
},
{
id: 4,
name: 'root2',
children: [
{ id: 5, name: 'child2.1' },
{
id: 6,
name: 'child2.2',
children: [{
id: 7,
name: 'subsub',
children: [{
id: 8,
name: 'subsubsub'
}]
}]
}
]
}
];
You can modify your original nodes array using array#forEach and recursive approach. Iterate through each key of node if the key includes key word delete it and if it contains children call deleteKey function again.
var nodes = [ { id: 1, name: 'root1', key: 'value1', key1: 'value2', children: [ { id: 2, name: 'child1' }, { id: 3, name: 'child2' } ] }, { id: 4, name: 'root2', key3: 'value3', key4: 'value4', children: [ { id: 5, name: 'child2.1' }, { id: 6, name: 'child2.2',key5: 'value5', key6: 'value6', children: [{ id: 7, name: 'subsub', children: [{ id: 8, name: 'subsubsub' }] }] } ] } ];
var deleteKey = (nodes) => {
nodes.forEach(node => {
Object.keys(node).forEach(k => {
if(k.includes('key'))
delete node[k];
if(k == 'children')
deleteKey(node[k]);
})
});
}
deleteKey(nodes);
console.log(nodes);
.as-console-wrapper { max-height: 100% !important; top: 0; }
In case you want a new array, you can use array#reduce and array#map.
var nodes = [ { id: 1, name: 'root1', key: 'value1', key1: 'value2', children: [ { id: 2, name: 'child1' }, { id: 3, name: 'child2' } ] }, { id: 4, name: 'root2', key3: 'value3', key4: 'value4', children: [ { id: 5, name: 'child2.1' }, { id: 6, name: 'child2.2',key5: 'value5', key6: 'value6', children: [{ id: 7, name: 'subsub', children: [{ id: 8, name: 'subsubsub' }] }] } ] } ];
var removeKey = (nodes) => {
return nodes.map(node => {
return Object.keys(node).reduce((r, k) => {
if(!k.includes('key'))
r[k] = node[k];
if(k == 'children')
r[k] = removeKey(node[k]);
return r;
},{});
});
}
console.log(removeKey(nodes));
.as-console-wrapper { max-height: 100% !important; top: 0; }
The function delete all the keys that are not id, name and children from your object
let nodes = [
{
id: 1,
name: 'root1',
key: 'value1',
key1: 'value2',
children: [
{ id: 2, name: 'child1' },
{ id: 3, name: 'child2' }
]
},
{
id: 4,
name: 'root2',
key3: 'value3',
key4: 'value4',
children: [
{ id: 5, name: 'child2.1' },
{
id: 6,
name: 'child2.2',
key5: 'value5',
key6: 'value6',
children: [{
id: 7,
name: 'subsub',
children: [{
id: 8,
name: 'subsubsub'
}]
}]
}
]
}
];
const getFinalNode = function(arr){
arr.forEach(function(obj, idx){
let tmpObj = {
id: obj.id,
name: obj.name,
}
if(obj.children && obj.children.length){
tmpObj.children = getFinalNode(obj.children)
}
arr[idx] = tmpObj
})
return arr
}
getFinalNode(nodes);
console.log(nodes)

Categories

Resources