Filter Multidimensional Array - javascript

I have my dataset configured as
var x = [
{"phaseName":"Initiation","phaseID":"595e382f1a1e9124d4e2600c"},
{"phaseName":"Execution","phaseID":"595e38321a1e9124d4e2600d"}
]
I want to write some function which give the output of filtered data.
For example
var y ="Initiation"
samplefunction(y)
and i get the whole line of {"phaseName":"Initiation","phaseID":"595e382f1a1e9124d4e2600c"}

Use Array#filter
var x = [{
"phaseName": "Initiation",
"phaseID": "595e382f1a1e9124d4e2600c"
},
{
"phaseName": "Execution",
"phaseID": "595e38321a1e9124d4e2600d"
}
];
function filter(phaseName) {
return x.filter(item => {
return item.phaseName === phaseName;
});
}
console.log(filter('Initiation'));

You can also use a simple for loop:
var x = [{
"phaseName": "Initiation",
"phaseID": "595e382f1a1e9124d4e2600c"
},
{
"phaseName": "Execution",
"phaseID": "595e38321a1e9124d4e2600d"
}
];
var y = "Initiation";
function samplefunction(value) {
var newArr = new Array(); //creating a new array to store the values
for (var i = 0; i < Object.keys(x).length; i++) { //looping through the original array
if (x[i].phaseName == value) {//check if the phase name coresponds with the argument
newArr.push(x[i]); //push the coressponding value to the new array
}
}
return newArr; //return the new array with filtered values
}
var result = samplefunction(y);
console.log(result);

You could test all properties for the wanted value and filter the array.
function filter(array, value) {
return array.filter(function (object) {
return Object.keys(object).some(function (key) {
return object[key] === value;
});
});
}
var data = [{ phaseName: "Initiation", phaseID: "595e382f1a1e9124d4e2600c" }, { phaseName: "Execution", phaseID: "595e38321a1e9124d4e2600d" }];
console.log(filter(data, "Initiation"));

Related

i couldn't figure out how can i make the object dynamically

as you can see i get the "p" array from a html form, and i want to make a dynamic object from the "p" array here
function filter(p){
var obj;
console.log(p);//[ 'Grade', '>','123']
if(p[1]== ">"){p[1]=gt}
obj = {
$and:[
{p[0]: {$p[1]: p[3}}
]
}
return obj;
}
to pass it to this aggregation function:
async function query(DS,filter,q1,q2,q3){
arr.length = 0;
var obj;
var x = [];
var y = [];
var filtered;
const projection = { _id: 0 }; projection[q1] = 1; projection[q2] = 1;
const grouping ={}; grouping[q1]=q1; grouping[q2] = q2;
filtered = await DS.aggregate([
{$project: projection},
{$match: filter}
]).toArray()
}
if(q3 == ""){
for (let i = 0; i < filtered.length; i++) {
obj = filtered[i]
x.push(obj[q1])
y.push(obj[q2])
}
arr.push(x)
arr.push(y)
return arr;
}
i couldn't figure out how can i make the object dynamically.
If you want to generate the objects keys dynamically, you can compute them by using square brackets where the key(s) would go.
For your case, you can replace this:
if(p[1]== ">"){p[1]=gt}
obj = {
$and:[
{p[0]: {$p[1]: p[3}}
]
}
with this:
if (p[1] === ">") { p[1] = 'gt' }
obj = {
$and:[
{
[p[0]]: {
['$' + p[1]]: p[2]
}
}
]
}
and you will get this object as a result (when using your provided input):
{"$and": [
{
"Grade": {
"$gt": "123"
}
}
]
}
Hope that helps!

count the occurrence of a string from a value in array of objects

I have an array of objects like this:
[
{
x_issue: 'Cost, Taste, Other',
y_a_issue: 'Spillover'
},
{
x_issue: 'Cost, Taste',
y_a_issue: 'Spillover'
},
{
x_issue: 'Taste, Other',
y_a_issue: 'Packaging'
}
]
I need the result array to be like this:
{
"x": {
"response": {
"Cost": 2,
"Taste": 3,
"Other": 2
}
},
"y_a": {
"response": {
"Spillover": 2,
"Packaging": 1
}
}
}
Also, I have an array of parameters
['x', 'y_a', 'z']
Here there could many more parameters like x, y. the last string issue remains constant in every parameter. And it is grouped by the occurrence.
Cost has been entered twice, Taste entered thrice.
How can I do that in javascript? I am using lodash.
This is what I was trying:
Here data is the array of object which is a mongodb object. And parameters is the array of parameters that I mentioned above.
let obj = {};
_.forEach(data, (v, k) => {
obj.parameters = [];
_.forIn(v.toJSON(), (val, key) => {
// let count = 0;
var bucket = _.find(parameters, k => _.startsWith(key, k));
if (bucket) {
if (key === `${bucket}_issue`) {
obj[bucket] = obj[bucket] || {};
obj[bucket]["response"] = obj[bucket]["response"] || {};
obj[bucket]["response"]["all"] = obj[bucket]["response"]["all"] || [];
obj[bucket]["response"]["all"].push(_.words(val));
}
}
});
});
In pure javascript you could do it like this using forEach() loop
var data = [{
x_issue: 'Cost, Taste, Other',
y_a_issue: 'Spillover'
}, {
x_issue: 'Cost, Taste',
y_a_issue: 'Spillover'
}, {
x_issue: 'Taste, Other',
y_a_issue: 'Packaging'
}]
var o = {}
data.forEach(function(e) {
Object.keys(e).forEach(function(k) {
var p = e[k].split(', ');
var re = /\_(?:.(?!\_))+$/
var key = k.split(re)[0];
if (!o[key]) o[key] = {response: {}};
p.forEach(function(a) {
o[key].response[a] = (o[key].response[a] || 0) + 1;
})
})
})
document.body.innerHTML = '<pre>' + JSON.stringify(o, 0, 4) + '</pre>';
You can use _.mergeWith() with a customizer function to achieve the merge you want, and then loop the result with _.transform() to remove the `_issue from each key:
var arr = [{
x_issue: 'Cost, Taste, Other',
y_a_issue: 'Spillover'
}, {
x_issue: 'Cost, Taste',
y_a_issue: 'Spillover'
}, {
x_issue: 'Taste, Other',
y_a_issue: 'Packaging'
}];
/** Create the mergeWithResponse method **/
var mergeWithResponse = _.partialRight(_.mergeWith, function(ov, sv) {
var oValue = ov ? ov : { // if the original value is undefined initialize it with a response property
response: {}
};
return sv.split(',').reduce(function(final, word) { // split the words of the source value and iterate them
var w = word.trim(); // remove space before and after the words
final.response[w] = (final.response[w] || 0) + 1; // add the word to the response and / or increment the counter
return final; // return the final value with the response object
}, oValue);
});
var result = _(mergeWithResponse.apply(_, [{}].concat(arr))) // add an empty object to the beginning of the array, and apply the new array as paramaters for mergeWithResponse
.transform(function(result, value, key) { // remove the "_issue" string an from each key, and create an object with the new keys
var k = key.replace('_issue', '');
result[k] = value;
});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.2/lodash.min.js"></script>

merging two array of objects with custom compare function with javascript

I have two array of objects like:
var A = [{title:"name1",count:5},{title:"name2",count:1},{title:"name3",count:3}];
and:
var B = [{title:"name2",count:7},{title:"name3",count:2},{title:"name4",count:3},{title:"name5",count:8}];
I need to merge this two array in one array and sum the "count" values in returned array when the "title" properties is same:
the last answer must be:
[{title:"name1",count:5},{title:"name2",count:8},{title:"name3",count:5},{title:"name4",count:3},{title:"name5",count:8}]
how can i do this???
You can use Array#forEach and Array#some to achieve a result
var M = A.concat(B)
var C = [];
M.forEach(function(a) {
var index;
if (C.some(function(c, i) { index = i; return a.title == c.title; })) {
C[index].count += a.count;
} else {
C.push(a);
}
});
console.log(C); // as you expect
Solution with Array.concat and Array.map functions:
var merged = A.concat(B), titles = [], result = [];
merged.map(function(obj){
if (titles.indexOf(obj.title) === -1) {
titles.push(obj.title);
result.push(obj);
} else {
result[titles.indexOf(obj.title)]['count'] += obj['count'];
}
});
console.log(result); // will output the expected array of objects
It can be done like this https://jsfiddle.net/menm9xeo/
var noMatch;
var A = [{title:"name1",count:5},{title:"name2",count:1},{title:"name3",count:3}];
var B = [{title:"name2",count:7},{title:"name3",count:2},{title:"name4",count:3},{title:"name5",count:8}];
//for each A, loop through B's. If a match is found combine the Counts in A.
for(var i=0;i<A.length;i++){
for(var j=0;j<B.length;j++){
if(A[i].title == B[j].title){
A[i].count += B[j].count;
}
}
}
//find all B's that were not combined with A in the previous step, and push them into A.
for(var i=0;i<B.length;i++){
noMatch = true;
for(var j=0;j<A.length;j++){
if(B[i].title == A[j].title){
B[i].count += A[j].count;
noMatch = false;
}
}
if(noMatch){A.push(B[i]);}
}
Heres a simple 3 line answer (minus the A/B vars); utilizes the fact that objects must have unique keys
var A = [{title:"name1",count:5},{title:"name2",count:1},{title:"name3",count:3}];
var B = [{title:"name2",count:7},{title:"name3",count:2},{title:"name4",count:3},{title:"name5",count:8}];
var o = {};
A.concat(B).forEach(function(a){o[a.title] = o.hasOwnProperty(a.title)? o[a.title]+a.count: a.count});
var AB = Object.keys(o).map(function(j){ return {title:j,count:o[j]} });
This proposal is merging and counting with a temporary object and Array#forEach()
The forEach() method executes a provided function once per array element.
var arrayA = [{ title: "name1", count: 5 }, { title: "name2", count: 1 }, { title: "name3", count: 3 }],
arrayB = [{ title: "name2", count: 7 }, { title: "name3", count: 2 }, { title: "name4", count: 3 }, { title: "name5", count: 8 }],
result = function (array) {
var o = {}, r = [];
array.forEach(function (a) {
if (!(a.title in o)) {
o[a.title] = { title: a.title, count: 0 };
r.push(o[a.title]);
}
o[a.title].count += a.count;
});
return r;
}(arrayA.concat(arrayB));
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Using lodash ._concat function :
var result = _.concat(A, B);
Fiddle

Merge array of javascript objects by property key

First of all: I already found this thread, which basically is exactly what I want, but I tried my best to apply it to my needs - I couldn't.
So, I have the following javascript function:
function loadRelationData(object) {
var result = [];
var parents = []
parents = getParentObjectsByObjectID(object['ObjectID']);
var tmpFirstObjects = [];
var tmpOtherObjects = [];
$.each(parents, function (_, parent) {
var keyName = 'Übergeordnete ' + parent['ObjectType'];
var pushObject = {};
if (parent['ObjectType'] == object['ObjectType']) {
pushObject['Fieldname'] = keyName;
pushObject['Value'] = parent['Name'];
tmpFirstObjects.push(pushObject);
} else {
pushObject['Fieldname'] = keyName;
pushObject['Value'] = parent['Name'];
tmpOtherObjects.push(pushObject);
}
});
result = result.concat(tmpFirstObjects).concat(tmpOtherObjects);
return result;
}
The parents array looks like this
And my function creates this result
This might be a bit complicated, but I need to split it up like this, because I need the order.
What I want is an array with both "TEC_MapLocations" joined together like this:
[
{Fieldname: 'Übergeordnete TEC_Equipment', Value: 'E0192'},
{Fieldname: 'Übergeordnete TEC_MapLocation', Value: ['M100', 'M200']},
{Fieldname: 'Übergeordnete TEC_FunctionalLocation', Value: 'FL456'}
]
Any ideas on how to alter my code to achieve the desired result right away or how to merge the results array?
edit: I used Joseph's solution and used the following (quick and dirty) sort function to get back my desired sorting:
output.sort(function (a, b) {
if (a.ObjectType == object.ObjectType) {
return -1
} else {
return 1
}
});
What you'd want to do first is build a hash with Fieldname as key, and an array as value. Then you'd want to use reduce to add the values into the hash and array. Then you can transform it into an array using Object.keys and map.
var input = [
{Name: 'M100', ObjectID: 1, ObjectType: 'TEC_MapLocation'},
{Name: 'M200', ObjectID: 2, ObjectType: 'TEC_MapLocation'},
{Name: 'FL456', ObjectID: 4, ObjectType: 'TEC_FunctionalLocation'},
{Name: 'E0192', ObjectID: 5, ObjectType: 'TEC_Equipment'}
];
var hash = input.reduce(function(carry, item){
// Create the name
var name = 'Übergeordnete ' + item.ObjectType;
// If array with name doesn't exist, create it
if(!carry[name]) carry[name] = [];
// If item isn't in the array, add it.
if(!~carry[name].indexOf(item.Name)) carry[name].push(item.Name);
return carry;
}, {});
// Convert the hash into an array
var output = Object.keys(hash).map(function(key, index, array){
return { Fieldname: key, Value: hash[key] }
});
document.write(JSON.stringify(output));
Try this:
function joinObjects( array ) {
// Start with empty array
var ret = new Array();
// Iterate array
for ( var i = 0; i < array.length; i++ ) {
// Search by fieldname
var match = false;
var j;
for ( j = 0; j < ret.length; j++ ) {
if ( array[i].Fieldname == ret[j].Fieldname ) { match = true; break; }
}
// If not exists
if ( !match ) {
// Intert object
ret.push({
Fieldname: array[i].Fieldname,
Value: new Array()
});
}
// Insert value
ret[j].Value.push( array[i].Value );
}
// Return new array
return ret;
}
http://jsfiddle.net/6entfv4x/

How to check if array is unique on specific object property?

I have an array of objects:
var array1 = [
{
property1: 10,
property2: "abc"
},
{
property1: 11,
property2: "def"
},
{
property1: 10,
property2: "ghi"
}
];
Now what I want is this array will be said not unique as per value of property1.
This means that this array contains 2 elements with property1=10, so the array does not contain unique value of property1.
To check this, I can use a for loop:
for (var i = 0; i < array1.length; i++) {
var array2 = array1.slice(); // copy array
array2.remove(array1[i]);
var temppropety1 = array1[i].property1;
for (var j = 0; j < array2.length; j++) {
if (array2[J].property1==temppropety1) {
return true;
}
}
}
But is there an easier way or a library to find this?
Here is a straightforward way to test for uniqueness on property1. Loop through the objects in the outer array and add each object's property1 to a temp array if it is not already in that temp array. If a duplicate value is encountered, return false meaning property1 is not unique.
function isUnique(arr) {
var tmpArr = [];
for(var obj in arr) {
if(tmpArr.indexOf(arr[obj].property1) < 0){
tmpArr.push(arr[obj].property1);
} else {
return false; // Duplicate value for property1 found
}
}
return true; // No duplicate values found for property1
}
Demo: http://jsbin.com/lohiqihipe/1/
First, you could reduce (aggregate) the objects by grouping them by the value of property1:
var grouped = array.reduce(function(grouped, item) {
var propertyValue = item.property1;
grouped[propertyValue] = (grouped[propertyValue] || 0) + 1;
return grouped;
}, {});
Then you check that every key of the resulting object has a value of 1:
var result = Object.keys(grouped).every(function(key) {
return grouped[key] === 1;
});
I suggest that array can be quite big so I'd prefer not to copy it and just validate properties.
Also it is not an option to use map function of array because in this case you won't be able to break a cycle on first match:
var equals = function(array) {
var co = {};
var unique = true;
for(var i = 0; i < array.length; i++) {
var o = array[i];
if (co[o.property1]) {
unique = false;
break;
} else {
co[o.property1] = true;
}
}
return unique;
};
You can convert your array to flat structure:
array1.map(function(item) { return item.property1; });
and now your problem simplify to check duplicates in simple array
var array1 = ["a","b","b","c","d","e","f"];
var uniqueItems = [];
$.each(array1, function(i, el){
if($.inArray(el, uniqueItems) === -1) uniqueItems.push(el);
});
References:
https://stackoverflow.com/a/840808/4772988
https://stackoverflow.com/a/9229932/4772988
You can use a couple of helpers to abstract it:
var uniqBy = function(f, xs) {
var seen = []
return xs.filter(function(x) {
var fx = f(x)
if (seen.indexOf(fx) > -1) return
seen.push(fx)
return true
})
}
var dot = function(k) {
return function(obj) {
return obj[k]
}
}
Then filter out duplicates by the property, and compare the length of the result to the original array. If they don't match, then they must not be unique:
var res = uniqBy(dot('property1'), array1)
var isUnique = array1.length === res.length
console.log(isUnique) // false
If you got only numbers or only strings to remove duplicates from, then you can improve performance by using an object instead of an array to keep track of elements seen so far.
You can use lodash library to achieve this.
Here is the library documentation: https://lodash.com/docs/4.17.5#filter
Method:-
function isDuplicatesPresent(list, propertyName){
return _.filter(list, function (value) {
return _.filter(list, function(innerValue){ reutrn innerValue[propertyName] === value[propertyName]}).length > 1;
}).length > 0;
}
Example:-
var users = [
{ user: 'barney', age: 36, active: true },
{ user: 'fred', age: 40, active: false },
{ user: 'barney', age: 37, active: true}
];
let duplicates = _.filter(users, function (value) {
return _.filter(users, {user:value.user}).length > 1;
});
Result:
console.log(duplicates)
> [
{"user": "barney","age": 36,"active": true},
{"user": "barney","age": 37,"active": true}
];

Categories

Resources