'Is there a more functional way to merge and foreach/sort two arrays in TypeScript, React?
I'm learning React and TypeScript. For sake of practise, I've tried to create a calculator design by merging two arrays to map a single array onto the grid (display: grid; grid-template-columns: repeat(4, 1fr);
).
Now I'm wondering if there's a way to do this more effectively with better readability, preferably with functional programming standards?
const numbers = [3, 2, 1, 6, 5, 4, 9, 8, 7]
const signs = ["AC", "√", "%", "÷", "*", "-", "+", "00", "0", ".", "="]
const alphanumeric = numbers.toString().split(",").concat(signs)
const fillButtons = () => {
const sortedArray: Array<string> = []
let findSignIndex = 0
let findNumberIndex = numbers.length - 1
alphanumeric.forEach((_: string, index: number) => {
if (index <= 3) {
sortedArray.push(signs[findSignIndex++])
}
else if (index % 3 === 0 && findNumberIndex >= 0) {
sortedArray.push(numbers[findNumberIndex--].toString())
sortedArray.push(signs[findSignIndex++])
}
else if (findNumberIndex >= 0) {
sortedArray.push(numbers[findNumberIndex--].toString())
}
else if (findSignIndex >= 0 && index < (alphanumeric.length - 3)) {
sortedArray.push(signs[findSignIndex++])
}
});
return sortedArray
}
This is the resulting array:
['AC', '√', '%', '÷', '7', '8', '9', '*', '4', '5', '6', '-', '1', '2', '3', '+', '00', '0', '.', '=']
This is the map:
{fillButtons().map((character: string, index: number) => (
<button key={index} className="calculator__button">
{character}
</button>
))}
This is the result:
Solution 1:[1]
The problem
We want to assign "sign"s to corresponding "slots", but we need to find a declarative way to do it.
Actually there can not be a sensible "functional programming" solution, because the problem is not in the complexity of computation logic, but in the way that we want to store placement of buttons.
Solution 1
Use declarative power of grid template areas and forget about reordering arrays completely.
.controls {
display: grid;
grid-template-areas:
"AC sqrt percent div"
"n7 n8 n9 mul"
"n4 n5 n6 sub"
"n1 n2 n3 sum"
"doublezero n0 dot eq";
}
const numbers = [3, 2, 1, 6, 5, 4, 9, 8, 7];
const signs = ["AC", "?", "%", "÷", "*", "-", "+", "00", "0", ".", "="];
// but we are forced to store this clunky map, because
// ? % ÷ * + . = can not be used inside a grid area name
const signsToGridLabels = {
"AC": 'AC',
"?": 'sqrt',
"%": 'percent',
"÷": 'div',
"*": 'mul',
"-": 'sub',
"+": 'sum',
".": 'dot',
"=": 'eq',
"00": 'doublezero',
};
const App = () => (
<>
<div className="display"></div>
<div className="controls">
{numbers.concat(signs).map((el) => {
return (<div style={{ gridArea: signsToGridLabels[el] ?? `n${el}` }}>{el}</div>)
})}
</div>
</>
);
(Not so much of a) Solution 2
Define a single "template" with grid-template-columns: repeat(4, 1fr);
const template = [
'AC', '?', '%', '÷',
'7', '8', '9', '*',
'4', '5', '6', '-',
'1', '2', '3', '+',
'00', '0', '.', '='
];
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Temoncher |