Publicado el 21.08.2022 a las 10:44
En esta prueba técnica nos piden hacen un INNER JOIN entre dos arrays de objetos JSON.
La operación INNER JOIN es muy utilizada en bases de datos SQL.
Se trata de combinar los registros de dos tablas si hay valores coincidentes en algún campo común.
Un ejemplo de consulta SQL con la operación INNER JOIN es:
SELECT CategoryName, ProductName FROM Categories INNER JOIN Products ON Categories.CategoryID = Products.CategoryID;
Dado dos listas de objetos se pide crear una función que aceptará 3 parámetros:
La función debe devolver un listado de contactos con los datos combinados de ambas listas o arrays.
Se hace especial hincapié en que la función debe tener un buen rendimiento 🚩
Al leer buen rendimiento se me encienden alarmas de usar mientras menos bucles mejor porque la solución que de primeras se me ocurre es recorrer con un bucle el primer array y por cada item hacer otro bucle con ese item buscando en el segundo array.
El rendimiento de los bucles anidados no es bueno, así que se me ocurre que lo haré con una tabla de hash. Particularmente me encanta esta estructura de datos.
Los datos de la prueba son:
const contacts = [ { id: 7, email: '[email protected]', first_name: 'Michael', last_name: 'Lawson', avatar: 'https://reqres.in/img/faces/7-image.jpg', }, { id: 8, email: '[email protected]', first_name: 'Lindsay', last_name: 'Ferguson', avatar: 'https://reqres.in/img/faces/8-image.jpg', }, { id: 9, email: '[email protected]', first_name: 'Tobias', last_name: 'Funke', avatar: 'https://reqres.in/img/faces/9-image.jpg', }, { id: 10, email: '[email protected]', first_name: 'Byron', last_name: 'Fields', avatar: 'https://reqres.in/img/faces/10-image.jpg', }, { id: 11, email: '[email protected]', first_name: 'George', last_name: 'Edwards', avatar: 'https://reqres.in/img/faces/11-image.jpg', }, { id: 12, email: '[email protected]', first_name: 'Rachel', last_name: 'Howell', avatar: 'https://reqres.in/img/faces/12-image.jpg', }, { id: 7, email: '[email protected]', first_name: 'Michael', last_name: 'Lawson', avatar: 'https://reqres.in/img/faces/7-image.jpg', }, { id: 8, email: '[email protected]', first_name: 'Lindsay', last_name: 'Ferguson', avatar: 'https://reqres.in/img/faces/8-image.jpg', }, { id: 9, email: '[email protected]', first_name: 'Tobias', last_name: 'Funke', avatar: 'https://reqres.in/img/faces/9-image.jpg', }, { id: 10, email: '[email protected]', first_name: 'Byron', last_name: 'Fields', avatar: 'https://reqres.in/img/faces/10-image.jpg', }, { id: 11, email: '[email protected]', first_name: 'George', last_name: 'Edwards', avatar: 'https://reqres.in/img/faces/11-image.jpg', }, { id: 12, email: '[email protected]', first_name: 'Rachel', last_name: 'Howell', avatar: 'https://reqres.in/img/faces/12-image.jpg', } ] const meetingContacts = [ { id: 1, email: '[email protected]', first_name: 'Michael', confirmed: true }, { id: 2, email: '[email protected]', first_name: 'George', confirmed: true }, { id: 3, email: '[email protected]', first_name: 'Lindsay', confirmed: true } ]
Como podemos ver nos dan un listado de contactos y un listado de asistentes a una reunión.
Tenemos que crear una función que pasándole como parámetros los dos listados y un campo de búsqueda devuelva un listado combinando los datos comunes de ambas listas o arrays.
function innerJoin( firstArray: { id: number, email: string, first_name: string, last_name: string, avatar: string }[], secondArray: { id: number, email: string, first_name: string, confirmed:boolean }[], key: 'email' | 'first_name'): Array<object> { const hashMap=new Map; firstArray.forEach(item=> hashMap.set(item[key],item)); const result:{}[]=[]; secondArray.forEach(item=>{ const getItemFromMap = hashMap.get(item[key]); if (!getItemFromMap) return; const {id:idFirstItemArray, ...restFirstItemArray} = getItemFromMap; //uso la desesctruturación para extraer el id y poder renombrarlo const {id:idSecondItemArray, ...restSecondItemArray} = item; //uso la desesctruturación para extraer el id y poder renombrarlo result.push({idFirstItemArray,...restFirstItemArray, idSecondItemArray, ...restSecondItemArray}); }) return result; } console.log(innerJoin(contacts,meetingContacts,"email")) //en el key sólo podré pasarle el email o el first_name como parámetro
Algo que da muchos puntos es que al tipar el parámetro de la key sólo permitirá aceptar o email o first_name que son los campos comunes. Esto evita muchos problemas de desarrollo en el futuro. Es la magia de TypeScript.
Si te fijas, como cada lista tiene su propio campo id que no coincide, lo que he hecho es (usando la desestructuración de objetos) sacar el id de cada lista y renombrarlo para posteriormente añadirlo a la solución.
[LOG]: [{ "idFirstItemArray": 7, "email": "[email protected]", "first_name": "Michael", "last_name": "Lawson", "avatar": "https://reqres.in/img/faces/7-image.jpg", "idSecondItemArray": 1, "confirmed": true }, { "idFirstItemArray": 11, "email": "[email protected]", "first_name": "George", "last_name": "Edwards", "avatar": "https://reqres.in/img/faces/11-image.jpg", "idSecondItemArray": 2, "confirmed": true }, { "idFirstItemArray": 8, "email": "[email protected]", "first_name": "Lindsay", "last_name": "Ferguson", "avatar": "https://reqres.in/img/faces/8-image.jpg", "idSecondItemArray": 3, "confirmed": false }]
Hasta luego 🖖