I have an array of data that look like this, some of them are group type and contain children like standalone type
const myArray = [{
name: "Bitcoin",
balance: 10,
}, {
name: "ETH",
tokens: [{
name: "Ethereum",
balance: 0,
}, {
name: "Chainlink",
balance: 5,
}],
}, {
name: "Solona",
balance: 0,
}];
I want to make a search and filter tag such as the balance. I have achieved it with this approach.
const searchString = "";
const hideZeroBalanceAsset = false;
const filterGroupToken = (groupToken) => {
const shallowCopy = { ...groupToken };
if (searchString) {
const isGroupNameMatchedSearch = shallowCopy.name
.toLowerCase()
.includes(searchString);
const subTokensMatchedSearch = shallowCopy.tokens.filter((subToken) =>
subToken.name.toLowerCase().includes(searchString)
);
if (subTokensMatchedSearch.length === 0 && !isGroupNameMatchedSearch)
return undefined;
if (
subTokensMatchedSearch.length > 0 &&
(subTokensMatchedSearch, length < shallowCopy.tokens.length)
) {
shallowCopy.tokens = subTokensMatchedSearch;
}
}
if (hideZeroBalanceAsset) {
const subTokensNonZeroBalance = shallowCopy.tokens.filter(
(subToken) => subToken.balance > 0
);
if (subTokensNonZeroBalance.length === 0) return undefined;
if (
subTokensNonZeroBalance.length > 0 &&
subTokensNonZeroBalance.length < shallowCopy.tokens.length
) {
shallowCopy.tokens = subTokensNonZeroBalance;
}
}
return shallowCopy;
};
const filterSingleToken = (token) => {
if (searchString) {
if (!token.name.toLowerCase().includes(searchString)) return undefined;
}
if (hideZeroBalanceAsset) {
if (token.balance === 0) return undefined;
}
return token;
};
const findMatchedTokensReducer = (matchedTokens, nextToken) => {
if (Array.isArray(nextToken.tokens)) {
const nextMatchedToken = filterGroupToken(nextToken);
if (nextMatchedToken) matchedTokens.push(nextMatchedToken);
} else {
const nextMatchedToken = filterSingleToken(nextToken);
if (nextMatchedToken) matchedTokens.push(nextMatchedToken);
}
return matchedTokens;
};
const myArray = [{
name: "Bitcoin",
balance: 10,
}, {
name: "ETH",
tokens: [{
name: "Ethereum",
balance: 0,
}, {
name: "Chainlink",
balance: 5,
}],
}, {
name: "Solona",
balance: 0,
}];
const filteredArray = myArray.reduce(findMatchedTokensReducer, []);
console.log({ filteredArray });
.as-console-wrapper { min-height: 100%!important; top: 0; }
However I feel this implementation bloated and inefficiently. Especially, the filterGroupToken function but because I want to show all the children of the group type when the search string matches its name.