How can I make the code more readable and more efficient? (provided code is O(n²) time, but intuition says it can be pre-processed and done in O(n) time)
Description
- it tags the first and last of each object matching a condition, and removes all objects without tags
- the input order must be preserved
- the first match may also be the last match (see "Bobby" example)
- it must use at most ES6 functions
Input
[
{ name: "John Smith", value: 5 },
{ name: "Jane Doe", value: 3 },
{ name: "John Smith", value: 1 },
{ name: "John Smith", value: 3 },
{ name: "Jane Doe", value: 5 },
{ name: "Bobby", value: 2 },
]
Output
[
{ name: "John Smith", value: 5, tags: ["first"] },
{ name: "Jane Doe", value: 3, tags: ["first"] },
// removed since it is not the first nor last of "John Smith": { name: "John Smith", value: 1, tags: [] },
{ name: "John Smith", value: 3, tags: ["last"] },
{ name: "Jane Doe", value: 5, tags: ["last"] },
{ name: "Bobby", value: 2, tags: ["first", "last"] },
]
Code
Only "PROCESSING" needs to be reviewed.
/* SETUP */
const arrays = [{
name: "John Smith",
value: 5
},
{
name: "Jane Doe",
value: 3
},
{
name: "John Smith",
value: 1
},
{
name: "John Smith",
value: 3
},
{
name: "Jane Doe",
value: 5
},
{
name: "Bobby",
value: 2
},
]
const expectedTaggedArrays = [{
name: "John Smith",
value: 5,
tags: ["first"]
},
{
name: "Jane Doe",
value: 3,
tags: ["first"]
},
{
name: "John Smith",
value: 3,
tags: ["last"]
},
{
name: "Jane Doe",
value: 5,
tags: ["last"]
},
{
name: "Bobby",
value: 2,
tags: ["first", "last"]
},
]
/* PROCESSING */
// set all elements to have empty list of tags
let taggedArrays = arrays.map((x) => ({ ...x,
tags: []
}))
for (let i = 0; i < taggedArrays.length; i++) {
// function to compare for "equality"
const hasSameName = (x) => x.name === taggedArrays[i].name
// tag if first time name seen
const firstMatchingIndex = taggedArrays.findIndex(hasSameName)
if (firstMatchingIndex === i) {
taggedArrays[firstMatchingIndex].tags.push("first")
}
// tag if last time name seen
const lastMatchingIndex = taggedArrays.findLastIndex(hasSameName)
if (lastMatchingIndex === i) {
taggedArrays[lastMatchingIndex].tags.push("last")
}
}
// remove all elements that have not been tagged
taggedArrays = taggedArrays.filter((x) => x.tags.length)
/* TEST */
const isCorrect =
JSON.stringify(taggedArrays) == JSON.stringify(expectedTaggedArrays)
isCorrect ? console.info("correct") : console.error("incorrect")