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>
Related
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);
I wonder how to create a new array with keys from the existing array object's property values. I know how to do it with a loop but is there is a better solution such as using the array.map function?
Input Array:
[ {id: 1, name: 'John', surname: 'Smith'}, {id: 2, name: 'Peter', 'Black'} ]
Requested result:
[ { 'John' : { id: 1, surname: 'Smith'}}, {'Peter': {id: 2, surname: 'Black'}} } ]
I still receive Error Unexpected token '.' with the key name.
var arr1 = [ {id: 1, name: 'John', surname: 'Smith'}, {id: 2, name: 'Peter', surname: 'Black'} ];
let arr2 = arr1.map( e => ( { e.name : {id: e.id, surname: e.surname } } ) );
You just need to wrap the dynamic key name in a square bracket [] like:
[e.name] : {id: e.id, surname: e.surname }
var arr1 = [ {id: 1, name: 'John', surname: 'Smith'}, {id: 2, name: 'Peter', surname: 'Black'} ];
let arr2 = arr1.map( e => ({ [e.name] : {id: e.id, surname: e.surname} }));
console.log(arr2)
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you want to use an expression as a key, then wrap it in square brackets:
let arr2 = arr1.map(e => ({[e.name]: {id: e.id, surname: e.surname}}));
You can do this way; You were too close, just you forget to bind the key using [obj.name]
let data = [{ id: 1, name: 'John', surname: 'Smith' }, { id: 2, name: 'Peter',surname: 'Black'}]
let finalResult =data.map(obj => ({ [obj.name]: { id: obj.id, surname: obj.surname } }))
console.log(finalResult)
I want to get the count of Items in array A that are in B and return an array C that contains the count elements.
array A is:
arrA = [{id:1,name:"Nairobi"},{id:2,name:"New Delhi"},{id:3,name:"Singapore"},{id:4,name:"London"}]
array B is:
arrB = [{id:1,id_fk:1,name:"Steve"},{id:2,id_fk:1,name:"John"},{id:3,id_fk:2,name:"Stella"},{id:4,id_fk:3,name:"Kemi"},{id:5,id_fk:3,name:"Kelly"},{id:6,id_fk:4,name:"James"},{id:7,id_fk:4,name:"Marley"},{id:8,id_fk:4,name:"Oliver"}]
Using id_fk in array B as a "foreign key" for id in array A, the expected output is
[2,1,2,3]
My implementation code is
for (let arrayA of arrA){
let count = arrB.filter(a =>
{return a.id_fk === arrayA.id}).length;
}
You could take a Map and get the id as keys in the wanted order and reduce the second array for counting items with id_fk. As result take an array of the values of the map.
This approach uses a single loop for getting the id as keys and another loop for counting.
var arrA = [{ id: 1, name: "Nairobi" }, { id: 2, name: "New Delhi" }, { id: 3, name: "Singapore" }, { id: 4, name: "London" }],
arrB = [{ id: 1, id_fk: 1, name: "Steve" }, { id: 2, id_fk: 1, name: "John" }, { id: 3, id_fk: 2, name: "Stella" }, { id: 4, id_fk: 3, name: "Kemi" }, { id: 5, id_fk: 3, name: "Kelly" }, { id: 6, id_fk: 4, name: "James" }, { id: 7, id_fk: 4, name: "Marley" }, { id: 8, id_fk: 4, name: "Oliver" }],
result = Array.from(arrB
.reduce(
(m, { id_fk }) => m.set(id_fk, m.get(id_fk) + 1),
new Map(arrA.map(({ id }) => [id, 0]))
)
.values()
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
A result with a hash table and new objects with a count property.
var arrA = [{ id: 1, name: "Nairobi" }, { id: 2, name: "New Delhi" }, { id: 3, name: "Singapore" }, { id: 4, name: "London" }],
arrB = [{ id: 1, id_fk: 1, name: "Steve" }, { id: 2, id_fk: 1, name: "John" }, { id: 3, id_fk: 2, name: "Stella" }, { id: 4, id_fk: 3, name: "Kemi" }, { id: 5, id_fk: 3, name: "Kelly" }, { id: 6, id_fk: 4, name: "James" }, { id: 7, id_fk: 4, name: "Marley" }, { id: 8, id_fk: 4, name: "Oliver" }],
hash = {},
result = arrA.map(o => Object.assign(hash[o.id] = {}, o, { count: 0 }));
arrB.forEach(({ id_fk }) => hash[id_fk].count++);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I would do it like this. https://jsfiddle.net/6egs7uLy/
let counts = [];
arrA.forEach((item, index) => {
let count = 0;
arrB.forEach((item2, index) => {
if(item['id'] === item2['id_fk']) {
count++;
}
})
counts.push(count);
count = 0;
})
I want to combine two array together with lodash but there is a catch. If item has the same id, pick the one from the 2th array instead.
Example:
let arr1 = [{ id: 1, name: 'name1'}, { id: 2, name: 'name2'}, { id: 3, name: 'name3'}];
let arr2 = [{ id: 3, name: 'name3', score: 1}];
Expected result
[{ id: 1, name: 'name1'}, { id: 2, name: 'name2'}, { id: 3, name: 'name3', score: 1}];
Any idea, how to achieve that. Shoot me some idea. Thank you in advance.
In plain Javascript, you could use Map and check if an item of the second array exist, then take the one from the second otherwise from the first array.
let array1 = [{ id: 1, name: 'name1'}, { id: 2, name: 'name2'}, { id: 3, name: 'name3'}],
array2 = [{ id: 3, name: 'name3', score: 1}],
map2 = new Map(array2.map(a => [a.id, a])),
result = array1.map(a => map2.get(a.id) || a);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES5 with an object as hash table.
var array1 = [{ id: 1, name: 'name1'}, { id: 2, name: 'name2'}, { id: 3, name: 'name3'}],
array2 = [{ id: 3, name: 'name3', score: 1}],
map2 = array2.reduce(function (r, a) {
r[a.id] = a;
return r;
}, Object.create(null)),
result = array1.map(function (a) {
return map2[a.id] || a;
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
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)