checking array of objects - javascript

I wanted to check if each length of array of objects of inspectionScheduleUnitContactArtifactDto , if there is one inspectionScheduleUnitContactArtifactDto which length is equal to 0 return true , if each length of inspectionScheduleUnitContactArtifactDto not 0 or there is no 0 length from inspectionScheduleUnitContactArtifactDto return false;
#sample object
{
"id": 218,
"propertyId": 22977,
"inspectionScheduleUnitArtifactDto": [
{
"id": 524,
"inspectionScheduleUnitContactArtifactDto": [
{
"id": 1097,
"inspectionScheduleUnitArtifactId": 524,
"primaryContactName": "fsdfsdf",
}
],
},
{
"id": 525,
"inspectionScheduleUnitContactArtifactDto": [
{
"id": 1100,
"inspectionScheduleUnitArtifactId": 525,
"primaryContactName": "Name",
},
{
"id": 1101,
"inspectionScheduleUnitArtifactId": 525,
"primaryContactName": "342423432",
}
],
},
{
"inspectionScheduleUnitContactArtifactDto": [],
}
]
}

I believe your question can be simplified to the following:
If at least one object's inspectionScheduleUnitContactArtifactDto array is empty -> return true else return false.
The simplest way to do this is with some which will return true as soon as this condition is met rather than filtering through the entire array. If the condition is not met after searching through the array, then it will return false.
I used the following interfaces to make working with your object structure a bit easier:
export interface InspectionSchedule {
id: number,
propertyId: number,
inspectionScheduleUnitArtifactDto: InspectionScheduleUnitArtifactDto[]
}
export interface InspectionScheduleUnitArtifactDto {
id: number,
inspectionScheduleUnitContactArtifactDto: InspectionScheduleUnitContactArtifactDto[]
}
export interface InspectionScheduleUnitContactArtifactDto {
id: number,
inspectionScheduleUnitArtifactId: number,
primaryContactName: string
}
Importing this interface, you can use the following function:
containsZeroLengthArray(inspectionSchedule: InspectionSchedule) {
return inspectionSchedule.inspectionScheduleUnitArtifactDto
.some(contact => !contact.inspectionScheduleUnitContactArtifactDto.length);
}
Note: !someArray.length is true for an empty array.

I'm going to assume that you know the layout of your object and that you have classes that contain said data. I've created these sample classes to mock the data you showed here:
export class A {
constructor(id: number,
inspectionScheduleUnitArtifactId: number,
primaryContactName: string) { }
}
export class B {
constructor(id: number | null,
inspectionScheduleUnitContactArtifactDto: A[]) { }
}
export class C {
constructor(id: number, propertyId: number,
inspectionScheduleUnitArtifactDto: B[]) { }
}
You can use filter and check the length of the resulting array, like so:
// Setup mock data
const a1: A = new A(1097, 524, 'fsdfsdf');
const a2: A = new A(1100, 525, 'Name');
const a3: A = new A(1101, 525, '342423432');
const b1: B = new B(524, [a1]);
const b2: B = new B(525, [a2, a3]);
const b3: B = new B(null, []);
const c: C = new C(218, 22977, [b1, b2, b3]);
// Check if any of the inner inspectionScheduleUnitContactArtifactDtos are empty
const anyEmpty: boolean = c.inspectionScheduleUnitArtifactDto
.filter(x => x.inspectionScheduleUnitContactArtifactDto.length === 0)
.length > 0;

You can use a recursive function, and pass whatever key you want to determine if an empty property that has the same name exists in your complex objects:
var obj = {
"id": 218,
"propertyId": 22977,
"inspectionScheduleUnitArtifactDto": [
{
"id": 524,
"inspectionScheduleUnitContactArtifactDto": [
{
"id": 1097,
"inspectionScheduleUnitArtifactId": 524,
"primaryContactName": "fsdfsdf",
}
],
},
{
"id": 525,
"inspectionScheduleUnitContactArtifactDto": [
{
"id": 1100,
"inspectionScheduleUnitArtifactId": 525,
"primaryContactName": "Name",
},
{
"id": 1101,
"inspectionScheduleUnitArtifactId": 525,
"primaryContactName": "342423432",
}
],
},
{
"inspectionScheduleUnitContactArtifactDto": [],
}
]
}
function getEmptyProp(obj, key) {
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if ( obj[i].constructor === Array || obj[i].constructor === Object ) {
if (i == key) {
if (obj[i].length) {
if (getEmptyProp(obj[i], key)) return true;
} else {
return true;
}
} else {
if (getEmptyProp(obj[i], key)) return true;
}
} else {
if (i == key) return true;
}
}
return false;
}
// will return 'true' in this case
console.log(getEmptyProp(obj, 'inspectionScheduleUnitContactArtifactDto'));

Related

Convert one object in another object in TypeScript

I have an database result as shows in file:
So I have input data as follows:
const input = [
{
PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da',
PurchaseInvoicePosition_id: '44edfd7f-bc9e-4155-ad5c-5dace9c7c31a',
ProductStock_id: '0a701dbc-2661-4d67-b764-632cfb67334f',
},
{
PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da',
PurchaseInvoicePosition_id: '44edfd7f-bc9e-4155-ad5c-5dace9c7c31a',
ProductStock_id: '15278807-794a-4727-9bcb-f7f68dfb4d41',
},
{
PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da',
PurchaseInvoicePosition_id: '44edfd7f-bc9e-4155-ad5c-5dace9c7c31a',
ProductStock_id: '0ac9fcd7-73f0-47b1-8fbc-3948863e7a89',
},
{
PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da',
PurchaseInvoicePosition_id: '65e013a7-c7b2-47cf-88b7-2ab2d9bcd191',
ProductStock_id: null,
},
{
PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da',
PurchaseInvoicePosition_id: '8f00dde6-2548-46a7-a480-37e86a3ca895',
ProductStock_id: '1439dde4-d184-4c98-b0c4-6d3c88ce8496',
},
{
PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da',
PurchaseInvoicePosition_id: 'b48711b3-14b1-41ce-9f5f-4032297c1b8e',
ProductStock_id: null,
},
{
PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da',
PurchaseInvoicePosition_id: '4e22378d-cf56-4806-bea2-5ba0b220d3eb',
ProductStock_id: null,
},
];
I'd like to convert input object into output object as follows:
const output = [
{
PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da',
PurchaseInvoicePosition_ids: [
{
PurchaseInvoicePosition_id: '44edfd7f-bc9e-4155-ad5c-5dace9c7c31a',
ProductStock_ids: [
{
ProductStock_id: '0a701dbc-2661-4d67-b764-632cfb67334f',
},
{
ProductStock_id: '15278807-794a-4727-9bcb-f7f68dfb4d41',
},
{
ProductStock_id: '0ac9fcd7-73f0-47b1-8fbc-3948863e7a89',
},
],
},
{
PurchaseInvoicePosition_id: '65e013a7-c7b2-47cf-88b7-2ab2d9bcd191',
ProductStock_ids: [
{
ProductStock_id: null,
},
],
},
{
PurchaseInvoicePosition_id: '8f00dde6-2548-46a7-a480-37e86a3ca895',
ProductStock_ids: [
{
ProductStock_id: '1439dde4-d184-4c98-b0c4-6d3c88ce8496',
},
],
},
{
PurchaseInvoicePosition_id: 'b48711b3-14b1-41ce-9f5f-4032297c1b8e',
ProductStock_ids: [
{
ProductStock_id: null,
},
],
},
{
PurchaseInvoicePosition_id: '4e22378d-cf56-4806-bea2-5ba0b220d3eb',
ProductStock_ids: [
{
ProductStock_id: null,
},
],
},
],
},
];
Which should looks like on this image when folded:
And I don't know how to convert this way. I'm rather PHP developer, so doing this in JavaScript is hard for me.
I tried do this using some ways like three time iterate over this input object, searching uuid in arrays with no luck.
This input object can have multiple PurchaseInvoice_id which are connected with PurchaseInvoicePosition_id and with ProductStock_id.
Please find the Array.reduce implementation of your question
Logic
Loop through the input array.
Check if there is already a node with the current PurchaseInvoice_id present in the accumulator
If its not present, push the current node to accumulator in the desired pattern (Check Section 1 in the comment added in code)
If its present (Section 2 in code comment), find whether there is a node with current PurchaseInvoicePosition_id in the PurchaseInvoicePosition_ids of the found node
If that is not found (Section 3 in code comment), push your current PurchaseInvoicePosition_id and ProductStock_id to your accumulator.
If that is found (Section 4 in code comment) push your ProductStock_id to the ProductStock_ids of the found node.
Working Fiddle
const input = [
{ PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da', PurchaseInvoicePosition_id: '44edfd7f-bc9e-4155-ad5c-5dace9c7c31a', ProductStock_id: '0a701dbc-2661-4d67-b764-632cfb67334f', },
{ PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da', PurchaseInvoicePosition_id: '44edfd7f-bc9e-4155-ad5c-5dace9c7c31a', ProductStock_id: '15278807-794a-4727-9bcb-f7f68dfb4d41', },
{ PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da', PurchaseInvoicePosition_id: '44edfd7f-bc9e-4155-ad5c-5dace9c7c31a', ProductStock_id: '0ac9fcd7-73f0-47b1-8fbc-3948863e7a89', },
{ PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da', PurchaseInvoicePosition_id: '65e013a7-c7b2-47cf-88b7-2ab2d9bcd191', ProductStock_id: null, },
{ PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da', PurchaseInvoicePosition_id: '8f00dde6-2548-46a7-a480-37e86a3ca895', ProductStock_id: '1439dde4-d184-4c98-b0c4-6d3c88ce8496', },
{ PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da', PurchaseInvoicePosition_id: 'b48711b3-14b1-41ce-9f5f-4032297c1b8e', ProductStock_id: null, },
{ PurchaseInvoice_id: '8e54a096-568b-48d9-8461-826be53a32da', PurchaseInvoicePosition_id: '4e22378d-cf56-4806-bea2-5ba0b220d3eb', ProductStock_id: null, },
];
const output = input.reduce((acc, curr) => {
const purchaseInvoiceNode = acc.find((item) => item.PurchaseInvoice_id === curr.PurchaseInvoice_id);
if (purchaseInvoiceNode) {
// Section 2
const purchaseInvoicePositionNode = purchaseInvoiceNode.PurchaseInvoicePosition_ids.find((item) => item.PurchaseInvoicePosition_id === curr.PurchaseInvoicePosition_id);
if(purchaseInvoicePositionNode) {
// Section 4
purchaseInvoicePositionNode.ProductStock_ids.push({
ProductStock_id: curr.ProductStock_id,
})
} else {
// Section 3
purchaseInvoiceNode.PurchaseInvoicePosition_ids.push({
PurchaseInvoicePosition_id: curr.PurchaseInvoicePosition_id,
ProductStock_ids: [
{
ProductStock_id: curr.ProductStock_id
}
]
})
}
} else {
// Section 1
acc.push({
PurchaseInvoice_id: curr.PurchaseInvoice_id,
PurchaseInvoicePosition_ids: [
{
PurchaseInvoicePosition_id: curr.PurchaseInvoicePosition_id,
ProductStock_ids: [
{
ProductStock_id: curr.ProductStock_id
}
]
}
]
})
}
return acc;
}, []);
console.log(output)
I'm going to call the operation you're performing nestedGroups(). If you have an array of objects arr, and an ordered list of keys key1, key2, key3 (etc.) of the elements of arr, then nestedGroups(arr, key1, key2, key3) will return an object whose key will be a pluralized (just adding "s") version of key1, and whose value will be another array of groupings for the next key, and so on. This is hard to describe in words, so I'll just show an example:
const ng = nestedGroups(
[{ a: 1, b: 2 }, { a: 1, b: 3 }, { a: 4, b: 5 }, { a: 4, b: 6 }],
"a", "b"
);
/* const ng: { as: { a: number; bs: { b: number; }[]; }[]; } */
console.log(ng)
/* {
"as": [
{"a": 1, "bs": [{"b": 2}, {"b": 3}]},
{"a": 4, "bs": [{"b": 5}, {"b": 6}]}
]
} */
If we can implement and strongly type nestedGroups(), then your output will look like:
const r = nestedGroups(input,
"PurchaseInvoice_id", "PurchaseInvoicePosition_id", "ProductStock_id");
const output = r.PurchaseInvoice_ids;
/* const output: {
PurchaseInvoice_id: string;
PurchaseInvoicePosition_ids: {
PurchaseInvoicePosition_id: string;
ProductStock_ids: {
ProductStock_id: string | null;
}[];
}[];
}[] */
which you can verify is the type you want.
First let's implement it and worry about the strong types later:
// implementation
function nestedGroups(arr: Record<string, any>[], ...keys: string[]): any {
const [firstKey, ...restKeys] = keys;
if (firstKey === undefined) return {};
const retmap = new Map<any, any>();
arr.forEach(v => {
const val = v[firstKey];
if (!(retmap.has(val))) retmap.set(val, []);
retmap.get(val)!.push(v);
});
return {
[firstKey + "s"]: Array.from(retmap.entries()).map(([k, v]) =>
({ [firstKey]: k, ...nestedGroups(v, ...restKeys) }))
}
}
This is a recursive function which calls nestedGroups() inside itself unless the array of keys is empty. An empty keys array results in an empty return object. Otherwise, we use the first key firstKey to group the values in the array. Here I'm using a Map to store the values, so each time we see a property value at key1 that we've seen before, we push it onto the end of the array in that Map. And finally, the returned object has a single pluralized firstKey property whose value is an array of objects composed of information from the Map and from the recursive subcall to nestedGroups().
As for the typings, you'll end up needing recursive conditional types (to represent the recursion), variadic tuple types (to pull the array of keys apart) and template literal types (to add that "s" in the type system).
Let's define the NestedGroups<T, K> type to be the type of the return value of nestedGroups(arr, ...keys) when arr is of type T[] and keys is of type K:
type NestedGroups<T extends Record<K[number], Primitive>, K extends string[]> =
K extends [infer F, ...infer R] ? F extends string ? { [P in `${F}s`]:
Array<Pick<T, F> & NestedGroups<T, Extract<R, string[]>> extends
infer O ? { [P in keyof O]: O[P] } : never>; } : never : {};
type Primitive = null | undefined | number | bigint | string | boolean | symbol;
We are constraining T to have keys in K and whose values at those keys are Primitive values (which we define as the union of the types of JavaScript primitives) since those are easily comparable as Map keys. (If the different values of, say, PurchaseInvoicePosition_id were objects, then they probably wouldn't compare as equal, and it would be hard to group by them. Note that "x" === "x" is true but {x: 1} === {x: 1} is false).
Anyway, we will use NestedGroups<T, K> as the return value for nestedGroups(). We can keep the original implementation and just declare that nestedGroups is an overloaded function with a single call signature:
// call signature
function nestedGroups<T extends Record<K[number], Primitive>, K extends string[]>
(arr: T[], ...keys: K): NestedGroups<T, K>;
Okay, time to test it on your input:
const r = nestedGroups(input, "PurchaseInvoice_id", "PurchaseInvoicePosition_id", "ProductStock_id")
const output = r.PurchaseInvoice_ids;
/* const output: {
PurchaseInvoice_id: string;
PurchaseInvoicePosition_ids: {
PurchaseInvoicePosition_id: string;
ProductStock_ids: {
ProductStock_id: string | null;
}[];
}[];
}[] */
console.log(output);
/*
[{
"PurchaseInvoice_id": "8e54a096-568b-48d9-8461-826be53a32da",
"PurchaseInvoicePosition_ids": [
{
"PurchaseInvoicePosition_id": "44edfd7f-bc9e-4155-ad5c-5dace9c7c31a",
"ProductStock_ids": [
{
"ProductStock_id": "0a701dbc-2661-4d67-b764-632cfb67334f"
},
{
"ProductStock_id": "15278807-794a-4727-9bcb-f7f68dfb4d41"
},
{
"ProductStock_id": "0ac9fcd7-73f0-47b1-8fbc-3948863e7a89"
}
]
},
{
"PurchaseInvoicePosition_id": "65e013a7-c7b2-47cf-88b7-2ab2d9bcd191",
"ProductStock_ids": [
{
"ProductStock_id": null
}
]
},
{
"PurchaseInvoicePosition_id": "8f00dde6-2548-46a7-a480-37e86a3ca895",
"ProductStock_ids": [
{
"ProductStock_id": "1439dde4-d184-4c98-b0c4-6d3c88ce8496"
}
]
},
{
"PurchaseInvoicePosition_id": "b48711b3-14b1-41ce-9f5f-4032297c1b8e",
"ProductStock_ids": [
{
"ProductStock_id": null
}
]
},
{
"PurchaseInvoicePosition_id": "4e22378d-cf56-4806-bea2-5ba0b220d3eb",
"ProductStock_ids": [
{
"ProductStock_id": null
}
]
}
]
*/
Yes, that's the right type and the right output value.
There you go. The strong typing here might be overkill for your use case, but since you're asking about TypeScript and not just JavaScript, it might be useful to include it. If all you care about is the output value and not really the type, then you can forgo the typing and just leave it something wide like any. It's up to you.
Playground link to code

Recursive function to format nested arrays to match against arrays of conditions

Trying to write this eval function that takes in cases, loops through them and needs to check if it matches to a condition in a conditions array and returns true or false. I'm not sure how best to format the conditions array and run the matching on it. Conditions are nested, n-levels deep, so trying to get a recursive function.
console.log(cases.forEach(c => eval(formattedCondition, c.item)))
const conditions = [
"OR",
["AND",["==","maker","airbus"],["==","name","A320"]],
["AND",[ "==", "maker","boeing"]],
["OR",["==","name","B767"]]
]
const cases = [
{
"item": {
'maker': 'airbus',
'name':"A320",
}
// should return true for this case
},
{
"item": {
'maker': 'embraer',
'name':"e175",
}
// should return false for this case
},
{
"item": {
'maker': 'boeing',
}
// should return true for this case
},
{
"item": {
'name':"B767",
}
// should return true for this case
},
{
"item": {
'maker': 'boeing',
'name':"B777",
}
// should return false for this case
},
]
You could take an approach without eval and use the data to build expressions with a function for checking with equal and some quantizers for AND and OR.
const
conditions = ["OR", ["AND", ["==", "maker", "airbus"], ["==", "name", "A320"]], ["AND", ["==", "maker", "boeing"]], ["OR", ["==", "name", "B767"]]],
take = object => {
const
quantifiers = { AND: 'every', OR: 'some' },
operators = { '==': (a, b) => a == b },
evaluate = ([symbol, ...values]) => values.every(v => typeof v === 'string')
? operators[symbol](object[values[0]], values[1])
: values[quantifiers[symbol]](evaluate);
return evaluate;
},
cases = [
{ item: { maker: 'airbus', name: "A320" } }, // true
{ item: { maker: 'embraer', name: "e175" } }, // false
{ item: { maker: 'boeing' } }, // true
{ item: { name: "B767" } }, // true
{ item: { maker: 'boeing', name: "B777" } }, // true instead of false
],
result = cases.map(({ item }) => take(item)(conditions));
console.log(result);

filter object by two nested values

I'm facing a problem with filter method. On my page there's an input to search matches by team names. Filter value is being stored to React state. Matches object looks like this:
[
{
"id": 4,
"teamBlue": {
"id": 36,
"name": "nameForTeamBlue",
"playerList": [
{
[...]
}
]
},
"teamRed": {
"id": 37,
"name": "nameForTeamRed",
"playerList": [
{
[...]
}
]
},
"localDate": "2020-01-01",
"localTime": "00:00:00",
"referee": null,
"commentator1": null,
"commentator2": null,
"streamer": null,
"stage": {
"id": 2,
"name": "GROUPSTAGE"
},
"onLive": true,
"finished": false
},
]
I tried tons of methods to filter matches by team name, for example:
let criteria = {
teamBlue: {
name: this.state.filter
},
teamRed: {
name: this.state.filter
}
};
let filteredMatches = this.state.matches.filter(function(item) {
for (let key in criteria) {
if (item[key] === undefined || item[key] !== criteria[key])
return false;
}
return true;
});
console.log(filteredMatches);
but none of them worked.
Is there any way to filter these matches so when I type "blue" into my input, it will show all matches where team name contains "blue"?
Thanks in advance!
Try updating the condition to:
if (!item[key] || item[key].name !== criteria[key].name)
let filteredMatches = this.state.matches.filter(function(item) {
let flag = true;
for (let key in criteria) {
// update this to
if (!item[key] || item[key].name !== criteria[key].name)
flag = false;
}
return flag;
});
The name property is missing :
if (key in item && item[key].name !== criteria[key].name)
You're comparing objects with === which will return false. You either need to use a deep comparison method from a library, or implement it yourself like below:
const matches = [ {"id": 4,
"teamBlue": {
"id": 36,
"name": "nameForTeamBlue",
"playerList": []
},
"teamRed": {
"id": 37,
"name": "nameForTeamRed",
"playerList": []
},
}, {"id": 4,
"teamBlue": {
"id": 36,
"name": "nameForTeamBlue",
"playerList": []
},
"teamRed": {
"id": 37,
"name": "nameForTeamRead",
"playerList": []
},
}]
const criteria = {
teamBlue: {
name: 'nameForTeamBlue',
},
teamRed: {
name: 'nameForTeamRed',
}
}
const filteredMatches = matches.filter((item) => {
const allCriteriaMatched = Object.entries(criteria)
.every(([key, value]) => {
const matched = Object.entries(value).every(([criteriaKey, criteriaValue]) => {
const itemValue = item[key][criteriaKey]
const matched = itemValue == criteriaValue
if (!matched) console.log('Item %s does not matched criteria %s. Item\'s value is %s, but criteria value is %s', item[key]['id'], criteriaKey, itemValue, criteriaValue, criteriaValue)
return matched
})
if (!matched) return false
return true
}, {})
return allCriteriaMatched
})
console.log(filteredMatches);
Basically, you just need to go 1 level deeper :D if your criteria can have multiple nested objects, then there's no point doing it manually. You can try to map criteria to run against matches so that you don't use === on objects, but only primitives.

How do you loop through an array and only extract key:value that are specific values?

I would like to loop through an existing object and only extract specific keys to add to a new array.
The object looks like:
let lyricsData = {
"success": true;
"length": 50;
"result": [
{
"id_track": 123,
"haslyrics": true,
"id_artrist": 234,
},
{
"id_track": 567,
"haslyrics": false,
"id_artrist": 678,
}
]
}
I would only like to extract the results if "haslyrics" is true.
This is the block of code I've come up with:
1 function findHasLyrics(lyricsData) {
2 if (lyricsData.length === 0) {
3 console.log("findHasLyrics", null);
4 } else {
5 let hasLyricsTrue = [];
6 for (let i=0; i<lyricsData.length; i++) {
7 if (lyricsData.result[i].haslyrics === true) {
8 hasLyricsTrue.push(lyricsData.result[i]);
9 };
10 console.log("findHasLyrics", hasLyricsTrue);
11 };
12 };
13 };
Where is the code breaking? And how would I fix it?
Thanks in advance.
SOLUTION (EDITED). Thanks #StepUp and #Ankita.
I needed to keep the if-else statements. The lyricsData is dynamic and sometimes the length is 0. In that case, I need to pass a null through a function.
function findHasLyrics(lyricsData) {
if (lyricsData.length === 0) {
displayLyricsApi(null);
} else {
function findHasLyrics(lyricsData) {
return lyricsData.result.filter(f => f.haslyrics)
};
formatQueryLyrics(findHasLyrics(lyricsData));
};
}
Just use filter method:
lyricsData.result.filter(f=> f.haslyrics)
in your case:
function findHasLyrics(lyricsData) {
return return lyricsData.result.filter(f=> f.haslyrics);
};
An example:
var data = {
"success": true,
"length": 50,
"result": [{
"id_track": 123,
"haslyrics": true,
"id_artrist": 234,
},
{
"id_track": 567,
"haslyrics": false,
"id_artrist": 678,
}
]
};
function findHasLyrics(lyricsData) {
return lyricsData.result.filter(f=> f.haslyrics)
};
console.log(findHasLyrics(data));
Just use Array.filter() to filter the array with those objects that has haslyrics value as true. You can avoid the custom loops and logic with that function.
var obj = {
"success": true,
"length": 50,
"result": [
{
"id_track": 123,
"haslyrics": true,
"id_artrist": 234,
},
{
"id_track": 567,
"haslyrics": false,
"id_artrist": 678,
}
]
};
var res = obj.result.filter(({haslyrics}) => haslyrics);
console.log(res);
In your code you can update this way:
function findHasLyrics(lyricsData) {
if (lyricsData.length === 0) {
console.log("findHasLyrics", null);
} else {
var res = lyricsData.result.filter(({haslyrics}) => haslyrics);
console.log(res);
};
};
var obj = {
"success": true,
"length": 50,
"result": [{
"id_track": 123,
"haslyrics": true,
"id_artrist": 234,
},
{
"id_track": 567,
"haslyrics": false,
"id_artrist": 678,
}
]
};
findHasLyrics(obj);
The problem is that you've made an easy to make mistake in the for signature, docs here.
The second argument you're using doesn't return an Integer (number), lyricsData.result is an array, you want to return its .length, i.e:
for (let i=0; i<lyricsData.result.length; i++) {
...
}
However, I would advise you to use .filter as others have already suggested.

Trying to nest dynamically generated JSON based on user input in Javascript

I am fairly new at manipulating and writing JSON objects etc and I have this task to dynaimcally create JSON object based on user input. I have managed to create the object at 1 level, but i want to nest objects within objects, this is the desired output
// desired output
masterObj = [
{
"Market1": {
"Size1": {
"id": 1,
"reporting_label": "a",
...
},
"Size2": {
"id": 2,
"reporting_label": "a",
...
},
"Size3": {
"id": 3,
"reporting_label": "a",
...
},
"Size4": {
"id": 4,
"reporting_label": "a",
...
},
"Size5": {
"id": 5,
"reporting_label": "a",
...
}
},
"Market2": {...},
"Market3": {...},
"Market4": {...}
}
]
I am trying to use the push function on my masterObj and then in the for loop push the required objects into the child of the masterObj for each market. But all i can get to is having all objects on the same level (ie 9 objects), having started going round in circles now trying to solve this...
var masterObj = [{
}];
var requested = [
{
"Markets": {
// boolean values defined by checkboxes
"Market1": show_m1, "Market2": show_m2, "Market3": show_m3, "Market4": show_m4
},
"Sizes": {
// boolean values defined by checkboxes
"Size1": show_s1, "Size2": show_s2, "Size3": show_s3, "Size4": show_s4, "Size5": show_s5
}
}
]
for (var item of requested) {
if(item.Markets.Market1 === true ) {
var m1Obj = {Market1: {}}
masterObj.push(m1Obj);
if(item.Sizes.Size1 === true) {
var s1Obj = {
Size1: {}
}
masterObj.push(s1Obj);
}
if(item.Sizes.Size2 === true) {
var s2Obj = {
Size2: {}
}
sgObj.push(s2Obj);
}
if(item.Sizes.Size3 === true) {
var s3Obj = {
Size3: {}
}
sgObj.push(s3Obj);
}
if(item.Sizes.Size4 === true) {
var s4Obj = {
Size4: {}
}
masterObj.push(s4Obj);
}
if(item.Sizes.Size5 === true) {
var s5Obj = {
Size5: {}
}
masterObj.push(s5Obj);
}
}
if(item.Markets.Market2 === true ) {
var m2Obj = {
Market2: {}
}
// ouput each requested size
masterObj.push(m2Obj);
}
if(item.Markets.Market3 === true ) {
var m3Obj = {
Market3: {}
}
// ouput each requested size
masterObj.push(m3Obj);
}
if(item.Markets.Market4 === true ) {
var m4Obj = {
Market4: {}
}
// ouput each requested size
masterObj.push(m4Obj);
}
}
console.log(masterObj);
Any help with this would be amazing, In my head i believe I am close to the solution but at the moment its evading me!
Push won't work because your object has an array of one element.. which is an object not an array
masterObj = [ { ... } ]
More than likely you mean to have this kind of a construct:
masterObj = {
"Market1": {
"Size1": {
"id": 1,
"reporting_label": "a",
...
},
"Size2": {
"id": 2,
"reporting_label": "a",
...
},
"Size3": {
"id": 3,
"reporting_label": "a",
...
},
"Size4": {
"id": 4,
"reporting_label": "a",
...
},
"Size5": {
"id": 5,
"reporting_label": "a",
...
}
},
"Market2": {...},
"Market3": {...},
"Market4": {...}
}
which you can then access with
masterObj.Market7 = {...};
Or, if you need to access through a variable:
key = 'Market7';
masterObj[key] = {...};
EDIT: Note: JSONS has nothing to do with this question. You are dealing with straight objects and arrays. JSON applies only when you serialize/deserialize this object into a string -- usually for storage or transport.
With a little restructuring this is the code i have ended up with and I am now getting what i needed.
thanks Jeremy for pointing me in the right direction.
var requestedMarkets = [
{market: "Market1", display: show_m1, name: "m1"},
{market: "Market2", display: show_m2, name: "m2"},
{market: "Market3", display: show_m3, name: "m3"},
{market: "Market4", display: show_m4, name: "m4"}
];
var requestedSizes = [
{display: show_s1, size: '100x200', name: "S1"},
{display: show_s2, size: '100x300', name: "S2"},
{display: show_s3, size: '100x400', name: "S3"},
{display: show_s4, size: '100x500', name: "S4"},
{display: show_s5, size: '100x600', name: "S5"}
];
for (let item of requestedMarkets) {
if(item.display === true ) {
masterObj[item.market] = {};
for (let size of requestedSizes) {
var settings = {
id: uniqueID,
...
}
if(size.display === true) {
masterObj[item.market][size.name] = settings;
}
}
}
}
console.log(masterObj);

Categories

Resources