Reputation: 2558
I am having difficulty "compressing" the results of my grammar by stripping out null values and embedded arrays using Javascript. I am using the Nearley grammar checker which can run JS functions after a sentence is matched. Unfortunately you get the results of the full parse as a series of arrays. The following is an example of the output
[
[
[
[
[
[
[ [ 'climb'], [ [ null, 'to' ] ] ],
[ [ null, [ 'alt' ] ] ],
[ 332, [ null, [ 'km' ] ] ]
]
],
[ null ]
]
]
]
]
I would like to remove all those null
values and possibly "compress" all those arrays to something of the form:
[
[ 'climb', 'to' ],
[ 'alt', 332, 'km' ]
]
Or something similar. I have tried using various filter
methods without success.
Upvotes: 2
Views: 467
Reputation: 420
let resArr = [];
const findLoc = (arr, loc = []) => {
arr.map((d, i) => {
if (Array.isArray(d)) {
findLoc(d, [ ...loc, i ]);
} else {
if (d !== null) {
// console.log(d, loc);
resArr.push([...loc, d])
}
}
})
}
const a = [
[
[
[
[
[
[ [ 'climb'], [ [ null, 'to' ] ] ],
[ [ null, [ 'alt' ] ] ],
[ 332, [ null, [ 'km' ] ] ],
[ 56, [ null, null, [ [ [8] ] ] ] ]
]
],
[ null ]
]
]
]
];
findLoc(a);
let finalIndex = [...resArr.reverse()[0]];
finalIndex.splice(finalIndex.length -1 , 1);
finalIndex = resArr[0].indexOf(Math.max(...finalIndex));
const finalObj = {};
resArr.forEach((d) => {
finalObj[d[finalIndex]] = finalObj[d[finalIndex]] ? [...finalObj[d[finalIndex]], d[d.length -1]] : [d[d.length -1]]
});
console.log(Object.values(finalObj));
// [ [ "to", "climb" ], [ "alt" ], [ "km", 332 ], [ 8, 56 ] ]
change the input and test,
using matrix logic we can active this
Upvotes: 0
Reputation: 3589
One line solution:
1.Convert to string 2.Split to flat array 3. Remove empty values
Example:
var arr = [
[
[
[
[
[
[['climb'], [[null, 'to']]],
[[null, ['alt']]],
[332, [null, ['km']]]
]
],
[null]
]
]
]
];
var res = arr.toString().split(",").filter(item => item);
console.log(res);
Upvotes: 2
Reputation: 386560
You could filter an map with the same approach and flat all arrays.
const
filter = array => array.flatMap(v => Array.isArray(v)
? filter(v)
: v === null
? []
: v
),
array = [[[[[[[['climb'], [[null, 'to']]], [[null, ['alt']]], [332, [null, ['km']]]]], [null]]]]],
result = filter(array);
console.log(result);
An even shorter approach
const
filter = array => array
.flat(Infinity)
.filter(v => v !== null),
array = [[[[[[[['climb'], [[null, 'to']]], [[null, ['alt']]], [332, [null, ['km']]]]], [null]]]]],
result = filter(array);
console.log(result);
Upvotes: 2
Reputation: 13376
Really?.. how about
['climb', 'to', 'alt', 332, 'km']
then? – Peter Seliger
That's wonderful. Some sort of logical grouping would be preferable but hey if not...
...
const sample = [[[[
[[
[ [ 'climb'], [ [ null, 'to' ] ] ],
[ [ null, [ 'alt' ] ] ],
[ 332, [ null, [ 'km' ] ] ]
]],
[ null ]
]]]];
function flatOut(list, item) {
if (Array.isArray(item)) {
item = item.reduce(flatOut, []);
}
return list.concat(item);
}
const result = sample
.reduce(flatOut, [])
.filter(elm => (elm != null)); // non strict equality
//...in order to skip both values, undefined and null.
console.log('result :', result);
Upvotes: 2