Reputation: 324
I am currently trying to execute some operations after retrieving some data, the format I am trying to achieve is an array of strings:
let cleanedData = ['foo', 'bar']
The data I receive could either be an array of objects or an array of arrays that could have empty arrays that needs to be filtered out. So for example I can receive either: let notCleanedData = [['foo'],[],[],['bar']]
or this let notCleanedData = [{var: 'foo'}, {var: 'bar'}]
This is my code, it is working but I would like to improve it in a cleaner way or with ES6+ methods I have tried to use a filter function without success, any advice?
function filterInputData(notCleanedData) {
let cleanedInputData = [];
notCleanedData.forEach(input => {
if (input.length > 0) {
cleanedInputData.push(input)
}
if (input.var) {
cleanedInputData.push(input.var)
}
});
return cleanedInputData;
}
console.log(
filterInputData([['foo'],[],[],['bar']])
)
console.log(
filterInputData([{var: 'foo'}, {var: 'bar'}])
)
Upvotes: 3
Views: 595
Reputation: 1416
This is a simple one-line solution that comes to my mind without using any libraries:
const clean = (data) => data.map(item => item.var || item[0]).filter(item => item)
I tried it on the test inputs you provided:
const clean = (data) => data.map(item => item.var || item[0]).filter(item => item)
console.log(
clean([['foo'],[],[],['bar']])
)
console.log(
clean([{var: 'foo'}, {var: 'bar'}])
)
Upvotes: 2
Reputation: 503
In this situation you can use map to achieve what you want without foreach. Filter wont work since it can only remove elements from the list and not actually make any modifications to them.
function filterInputData(notCleanedData) {
let cleanedInputData = notCleanedData.map((input) => {
if (input.length > 0) {
return input;
}
if (input.var) {
return input.var;
}
}).filter(item => item !== undefined);
return cleanedInputData;
}
Upvotes: 0
Reputation: 18919
I'd bring in lodash to help here.
You can use flattenDeep to clean and flatten and map to test if the data includes objects.
Example:
function clean(data) {
return
_.chain(data)
.flattenDeep()
.map(x => {
if (x.var) {
return x.var;
}
return x;
})
.value();
}
console.log(
clean([['foo'],[],[],['bar']])
)
console.log(
clean([{var: 'foo'}, {var: 'bar'}])
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
Upvotes: 0
Reputation: 1311
Here is a much cleaner approach using reduce
:-
// This function assumes that the array inside the array has single value and the object inside array has only one key called var
function filterInputData(notCleanedData) {
return notCleanedData.reduce((acc, item) => {
if (item.length) acc.push(item[0]);
if (item.var) acc.push(item.var);
return acc;
}, [])
}
Hope you find this useful.
Upvotes: 0
Reputation: 3978
const input = [['foo'],[],[],['bar']]
const input2 = [{var: 'foo'}, {var: 'bar'}]
const clean = (data) => data && data[0].length // check type
? data.flat(1) // use new flat method if array
: (data || []).map((e) => e.var) // map objects otherwise
Upvotes: 1