I have a question. I had a task to write a function that:
- Will identify unique values in the array and for each one will return an object with the unique name, starting position in the array and the end position in the array, later transformed into the %.
- For the last object, the end position should be always "120%", hence the if in the code.
- EDIT: Let's assume the Test1 and Test2 can reappear, but they need to have separate starting and ending point - if they reappear later on in the array, we would treat them as unique values.
The function below works just fine, but I wonder how could I do that better. Or maybe using a loop or a hash map? I would like to improve my game!
const data = [
"Test1",
"Test1",
"Test2",
"Test2",
"Test2",
"Test3",
"Test3",
"Test3",
"Test3",
"Test4",
"Test4",
"Test4",
]
function calcComponent(data: string[]) {
const indices = data.map((el: string) => data.indexOf(el)*10);
const outputPosition = new Set(indices);
const outputNames = [...new Set(data)];
const output_array: number[] = [...outputPosition];
let result = outputNames.map((_, index) => {
if(index == outputNames.length-1){
return {
name: outputNames[index],
start: output_array[index],
end: "120%"
}
}
else{
return {
name: outputNames[index],
start: output_array[index].toString() "%",
end: output_array[index 1].toString() "%"
}
}
})
console.log(result)
}
calcComponent(data)
CodePudding user response:
Hey I made some assumptions for this solution, hope they're ok for you:
- Input array can be of arbitrary size
- Strings can re-appear in the array even after new ones appeared, meaning you can still have
Test1
even afterTest2
appears - Percentage is based on the actual array length so the last item has
end: 100%
and the first item hasstart: 0%
const data = [
"Test1",
"Test1",
"Test2",
"Test2",
"Test2",
"Test3",
"Test3",
"Test3",
"Test3",
"Test1",
"Test4",
"Test4",
"Test2",
"Test4",
"Test3"
]
function calcComponent(data: string[]) {
return data.filter((val, index, array) => array.indexOf(val) == index).map((val) => {
return {
name: val,
start: ((data.indexOf(val) / (data.length - 1)) * 100) "%", // or just (data.indexOf(val) * 10) "%"
end: ((data.lastIndexOf(val) / (data.length - 1)) * 100) "%" // or just (data.lastIndexOf(val) * 10) "%"
}
});
}
const result = calcComponent(data);
console.log({ result });
The output would be like:
{
"result": [
{
"name": "Test1",
"start": "0%",
"end": "64.28571428571429%"
},
{
"name": "Test2",
"start": "14.285714285714285%",
"end": "85.71428571428571%"
},
{
"name": "Test3",
"start": "35.714285714285715%",
"end": "100%"
},
{
"name": "Test4",
"start": "71.42857142857143%",
"end": "92.85714285714286%"
}
]
}
Updated Solution
Based on your comment here is a different version that does what you ask!
const data = [
"Test1",
"Test1",
"Test2",
"Test2",
"Test2",
"Test3",
"Test3",
"Test3",
"Test3",
"Test1",
"Test4",
"Test4",
"Test2",
"Test4",
"Test3"
]
type Rage = { name: string, start: string, end: string };
function calcComponent(data: string[]) {
return data.reduce((output, value, index, array) => {
const lastItem = output[output.length - 1];
if(lastItem && lastItem.name === value) {
lastItem.end = (index / (data.length - 1) * 100) "%";
} else {
output.push({
name: value,
start: (index / (data.length - 1) * 100) "%",
end: (index / (data.length - 1) * 100) "%"
})
}
return output;
}, [] as Rage[])
}
const result = calcComponent(data);
console.log({ result });
Output will be:
{
"result": [
{
"name": "Test1",
"start": "0%",
"end": "7.142857142857142%"
},
{
"name": "Test2",
"start": "14.285714285714285%",
"end": "28.57142857142857%"
},
{
"name": "Test3",
"start": "35.714285714285715%",
"end": "57.14285714285714%"
},
{
"name": "Test1",
"start": "64.28571428571429%",
"end": "64.28571428571429%"
},
{
"name": "Test4",
"start": "71.42857142857143%",
"end": "78.57142857142857%"
},
{
"name": "Test2",
"start": "85.71428571428571%",
"end": "85.71428571428571%"
},
{
"name": "Test4",
"start": "92.85714285714286%",
"end": "92.85714285714286%"
},
{
"name": "Test3",
"start": "100%",
"end": "100%"
}
]
}