Remove array from array if there is certain value in Object - javascript

I want to remove array which is inside of whole array if an object of its array has certain value. I searched the web and I saw removing object or array if it has certain value and I can't find that solves my problem.
I have objects of array which is again wrapped by array. It looks like below:
"products": [
[
{
"product.name": "A",
"remark.name": "Good"
},
{
"product.name": "B",
"remark.name": "Good"
}
],
[
{
"product.name": "A",
"remark.name": "Bad"
},
{
"product.name": "B",
"remark.name": "Good"
}
]
]
What I want
I want to omit the whole array which contains at least remark.name === Bad
So, I should get the final result like below.
"products": [
[
{
"product.name": "A",
"remark.name": "Good"
},
{
"product.name": "B",
"remark.name": "Good"
}
]
]
What I've tried
Below code
let result = [];
products.map((product) => {
var res = _.remove(product, function (n) {
return n["remark.name"] === "Fail";
});
result.push(res);
});
produces following result:
"products": [
[
{
"product.name": "A",
"remark.name": "Good"
},
{
"product.name": "B",
"remark.name": "Good"
}
],
[
{
"product.name": "B",
"remark.name": "Good"
}
]
]

Use Array#filter for filtering and as filter Array#every where remark.name is different from 'Bad'.
Note: Use single or double quotes for propertyname 'remark.name' because of the dot in it`s name.
let products = [
[
{
"product.name": "A",
"remark.name": "Good"
},
{
"product.name": "B",
"remark.name": "Good"
}
],
[
{
"product.name": "A",
"remark.name": "Bad"
},
{
"product.name": "B",
"remark.name": "Good"
}
]
];
let filtered = products.filter(arr => arr.every(obj => obj['remark.name'] !== 'Bad'));
console.log(filtered);

Related

Find an object and its parent by a property value of a nested object with Javascript

Given the following sample JSON (stringified from the corresponding JavaScript object), I need to extract this information:
Find the object in persons which has the reference = 2.
If a person with this reference was found, get the name of the person's parent element (here: "B").
In the end, I need to build a new object looking similar to this. This won't be problematic but I'm struggling with how to extract these objects from the source. I tried different approaches with find(), map(), flatMap() and filter() but none of them really worked.
{
companyName: "B",
person: {
"reference": 2,
"name": "Bob"
}
}
Source
{
"root": [
{
"companies": [
{
"name": "A",
"persons": [
{
"reference": 1,
"name": "Alex"
}
]
}
]
},
{
"companies": [
{
"name": "B",
"persons": [
{
"reference": 2,
"name": "Bob"
},
{
"reference": 3,
"name": "Charles"
}
]
}
]
}
]
}
If you're just interested in the name of the company you can find it using:
const reference = 2;
const company = data.root.flatMap(item => item.companies)
.find(company => company.persons.some(person => person.reference === reference));
const companyName = company?.name;
// or if you cannot use optional chaining
const companyName = (company || {}).name;
In data.root.flatMap(item => item.companies) we iterate through all items in root, for each item we select its companies property. Since we don't want a nested array we use flatMap() to flatten the result by 1 level. This leaves us with an array of companies.
After that we'll call find() on the companies array, since we are looking for a specific company name. The criteria of the company is that some() (1 or more) of the persons should match the provided reference. If no match is found null will be returned (from find()).
We then take the find() result (company) and navigate to the name via optional chaining ?.. This will return the name of the company if present, or undefined if company is null
You can use array.reduce here
let data = JSON.parse(`{
"root": [
{
"companies": [
{
"name": "A",
"persons": [
{
"reference": 1,
"name": "Alex"
}
]
}
]
},
{
"companies": [
{
"name": "B",
"persons": [
{
"reference": 2,
"name": "Bob"
},
{
"reference": 3,
"name": "Charles"
}
]
}
]
}
]
}`)
// GET ALL THE COMPANIES DATA
let companies = data.root.reduce(
(prevValue, currValue) => {
prevValue.push(...currValue.companies)
return prevValue
},
[]
)
// FIND AND CREATE EXPECTED RESULT SET
let results = companies.reduce(
(prevValue, currValue) => {
// loop inside a loop, mind it
let refPerson = currValue.persons.find((item)=> item.reference == 2)
if(refPerson){
prevValue.push({
companyName: currValue.name,
person: refPerson
})
}
return prevValue
},
[]
)
console.log(results)

Count in JavaScript

If I have an object like this in javascript, how can I count the number of elements in [A, B, C, D, etc.]?
{ "test" : [ "A", "B", "C", "D", ... ] }
And if i have:
{ "_id" : "1", "value" : { "test" : [ "A", "B", "C", "D" ] } }
{ "_id" : "2", "value" : { "test" : [ "A", "B", "C", "D", "E", "F" ] } }
How can I convert it to the following structure?
{ "_id" : "1", "value" : 4 }
{ "_id" : "2", "value" : 6 }
Thanks
Try the following:
var data = [{ "_id" : "1", "value" : { "test" : [ "A", "B", "C", "D" ] } },{ "_id" : "2", "value" : { "test" : [ "A", "B", "C", "D", "E","F" ] } }];
var arr = data.map((d) => {
d["value"] = d["value"].test.length;
return d;
});
console.log(arr);
EDIT
The more smart way is to simply use a forEach loop in the following way
var data = [{ "_id" : "1", "value" : { "test" : [ "A", "B", "C", "D" ] } },{ "_id" : "2", "value" : { "test" : [ "A", "B", "C", "D", "E","F" ] } }];
data.forEach((d) => {
d["value"] = d["value"].test.length;
});
console.log(data);
If can always do .length on an object check the example below:
var obj = { "test" : [ "A", "B", "C", "D", "E", "F"] };
console.log(obj.test.length)
EDIT:
For your second question
you can do
obj.value = obj.value.test.length;
var obj = { "_id" : "2", "value" : { "test" : [ "A", "B", "C", "D", "E", "F" ] } };
obj.value = obj.value.test.length;
console.log(obj)
As the answer changed from generic javascript to mongodb, I have to update the answer to reflect the question:
Instead of using map/reduce in mongo, consider using the aggregation framework mongodb provides, it allows for very powerful querying.
In this case, you want the $size operator
db.yourCollection.aggregate([
{ $project: { value: { $size: "$value.test" } } }
])
Unless explicitly removed, mongodb will always include the document _id so for this use case we only need to address the value, if you need any other value from the documents in your result-set, add them like:
db.yourCollection.aggregate([
{ $project: {
value: { $size: "$value.test" },
foo: '$foo',
bar: '$bar',
baz: '$baz',
} }
])
Original answer (pure js, no mongodb)
I suspect the example is actually part of an array
{ "_id" : "1", "value" : { "test" : [ "A", "B", "C", "D" ] } }
{ "_id" : "2", "value" : { "test" : [ "A", "B", "C", "D", "E" ] } }
So I assume you want to map a large set of records this way, and you don't want to (accidentally) destroy the original value property (as other answers do), here's how I'd do this:
const list = [
{ "_id" : "1", "value" : { "test" : [ "A", "B", "C", "D" ] } },
{ "_id" : "2", "value" : { "test" : [ "A", "B", "C", "D", "E" ] } }
];
// map the list into a new list of object containing the _id and value count
const mapped = list.map((record) => {
return {
_id: record._id,
// assuming there's only test and it's an array
value: record.value.test.length,
};
});
If value inside each record is an object which may contain zero or more arrays and you wish to count the total amount of items inside all of them, you can reduce the arrays into a total number.
const list = [
{ "_id" : "1", "value" : { "test" : [ "A", "B", "C", "D" ] } },
{ "_id" : "2", "value" : { "test" : [ "A", "B", "C", "D", "E" ] } },
{ "_id" : "3", "value" : { } },
{ "_id" : "4", "value" : { "test" : [ "A", "B" ], "test2" : [ "C", "D", "E" ] } },
];
// map the list into a new list of object containing the _id and value count
const mapped = list.map((record) => {
return {
_id: record._id,
// assuming there's zero or more arrays
value: Object.keys(record.value)
// filter out any non-array
.filter((key) => Array.isArray(record.value[key]))
// reduce the arrays into their combined length
.reduce((carry, key) => carry + record.value[key].length, 0),
};
});
console.log(mapped);
You can transform your array with a simple forEach loop - like below:
var data = [{
"_id": "1",
"value": {
"test": ["A", "B", "C", "D"]
}
},
{
"_id": "2",
"value": {
"test": ["A", "B", "C", "D", "E"]
}
}
];
var dataCount = [];
data.forEach(function(element) {
var newElement = {};
newElement._id = element._id;
newElement.value = element.value.test.length;
dataCount.push(newElement);
//console.log(newElement);
});
console.log(dataCount);

Remove object from array where sub-object matches a value

I'm currently attempting to sort through some values based on a query string. I'm able to target each target individually in this loop but cannot seem to properly remove them from the array. How can I remove certain values that match on target.target from targetList?'
targetList.forEach(function(target, key) {
var os = getParameterByName('os');
if (os == "android") {
if (target.target.includes(":IOS")) {
targetList.splice(key, 1);
}
} else if (os == "ios") {
if (target.target.includes(":ANDROID")) {
targetList.splice(key, 1);
}
}
if (target.target.includes(":IOS")) {
target.target = schools[target.target.replace(":IOS", "").toLowerCase()] + " (iOS)" || target.target;
}
if (target.target.includes(":ANDROID")) {
target.target = schools[target.target.replace(":ANDROID", "").toLowerCase()] + " (Android)" || target.target;
}
});
targetList contains an array like this:
[
{
"target": "t1",
"datapoints": [
[
51.0,
1483574400.0
],
[
54.0,
1485561600.0
],
[
54.0,
1485648000.0
]
]
},
{
"target": "t2",
"datapoints": [
[
56.0,
1484265600.0
],
[
70.0,
1484352000.0
],
[
71.0,
1484438400.0
],
[
51.0,
1484611200.0
]
]
},
]
What I'm attempting to do is that where a target matches certain criteria .includes() I want to remove the entire containing object/array.
It seems to me your code works just fine. I've created a snippet where I removed the extra processing, to show that what you have already does what you ask.
Is there a reason you're doing stuff to target.target once you've removed it from the array? Do you have a reference to the containing object somewhere else?
var targetList = [
{
"target": "t1",
"datapoints": [
[
51.0,
1483574400.0
],
[
54.0,
1485561600.0
],
[
54.0,
1485648000.0
]
]
},
{
"target": "t2",
"datapoints": [
[
56.0,
1484265600.0
],
[
70.0,
1484352000.0
],
[
71.0,
1484438400.0
],
[
51.0,
1484611200.0
]
]
},
];
targetList.forEach(function(target, key) {
if (target.target.includes("t2")) {
targetList.splice(key, 1);
}
});
console.log(targetList);

Extracting an object from an array in Javascript

I am working on a D3.JS chart using an array named "dataset" where each entry is an object with a key and value attributes, such as the following:
dataset=
[
{"key":"alpha", "value": [ {}, { } ...]},
{"key":"beta", "value": [ { }, { } ...]},
{"key":"gamma", "value": [ {}, { } ...]},
{"key":"delta", "value": [ { }, { } ...]}
];
I need to extract one of those objects to create a new array. I have tried the following:
filteredDataset = dataset.filter(function(d){ console.log("d",d); if(d.key === "gamma") return d});
I can see in the console that I am accessing each object in the dataset, but the resulting filteredDataset comes out empty. What am I doing wrong?
For clarity filter should be used by returning a boolean:
Like:
filteredDataset = dataset.filter(function(d){ return d.key === "gamma"})
And on my end the code
var dataset = [
{"key":"alpha", "value": [ {}, { }]},
{"key":"beta", "value": [ { }, { }]},
{"key":"gamma", "value": [ {}, { }]},
{"key":"delta", "value": [ { }, { }]}
];
filteredDataset = dataset.filter(function(d){ return d.key === "gamma"})
Outputs:
[ { key: 'gamma', value: [ {}, {} ] } ]
So please double check your code
dataset.filter(function(d){return d.key === 'gamma';});
This returns the data where key === gamma.
https://github.com/mbostock/d3/wiki/Selections#filter

How to filter array of object by multiples array/objects values

I need to filter an array of objects, like this:
var models = [
{
"family": "Applique",
"power":"8",
"volt":"12",
"color":"4100",
"type":"E27",
"ip":"20",
"dimensions":"230x92"
},
{
"family": "Lanterne",
"power":"20",
"volt":"230",
"color":"2700",
"type":"R7S",
"ip":"44",
"dimensions":"230x92"
},
{
"family": "Applique",
"power":"50",
"volt":"230",
"color":"",
"type":"GU10",
"ip":"20",
"dimensions":"227x227"
}
]
Based on a object like this:
var filter = {
"family":[
"Applique", "Faretto", "Lanterne"
],
"power":{
"less":[
"30"
],
"greater":[
],
"equal":[
]
},
"volt":[
"12", "230"
],
"color":[
],
"type":[
],
"ip":[
"20"
]
"dimensions":[
],
}
So, in this case, the result could be:
{
"family": "Applique",
"power":"8",
"volt":"12",
"color":"4100",
"type":"E27",
"ip":"20",
"dimensions":"230x92"
}
I've already read this other link: How to filter an array/object by checking multiple values, but I can not seem to adapt it to my case.
Thanks in advance!
EDIT: The condition on "power" property is not requested now
EDIT 2: Sorry, I've forgot to indicate that filter object can have multiple values for single property, like this:
var filter = {
"family":[
"Applique", "Faretto", "Lanterne"
],
...
"volt":[
"12", "230"
],
...
}
The solution using Array.filter, Array.indexOf and Object.keys functions:
var result = models.filter(function(obj){
var matched = true;
Object.keys(obj).forEach(function(k){
if (k === "power") { // The condition on "power" property is not requested now
return false;
}
if (filter[k] && filter[k].length && filter[k].indexOf(obj[k]) === -1) {
matched = false;
}
});
return matched;
});
console.log(JSON.stringify(result, 0, 4));
The console.log output:
[
{
"family": "Applique",
"power": "8",
"volt": "12",
"color": "4100",
"type": "E27",
"ip": "20",
"dimensions": "230x92"
}
]
Try lodash's _.filter
For filtering greater/lower than they give this example here:
_.filter(users, _.conforms({ 'age': _.partial(_.gt, _, 38) }));

Categories

Resources