2

I have two arrays of objects, one array contains objects that represent user data.

const userData = [
    {
      user_name: "Tania",
      email: "user-1@gmail.com",
      partido: "8",
      categoria_1: "1",
      categoria_2: "2",
      categoria_3: null
    },
    {
      user_name: "Jean",
      email: "user-2@gmail.com",
      partido: "24",
      categoria_1: null,
      categoria_2: "2",
      categoria_3: null
    },
    {
      user_name: "Vania",
      email: "user-4@gmail.com",
      partido: "13",
      categoria_1: null,
      categoria_2: "2",
      categoria_3: null
    },
    {
      user_name: "Rick",
      email: "user-4@gmail.com",
      partido: "13",
      categoria_1: "1",
      categoria_2: "2",
      categoria_3: "3"
    }
  ],

A second array contains objects that represent collections.

  collectionData = [
    {
      partido: "8",
      Equipo_Local: "Argentina",
      Equipo_Visitante: "Arabia Saudí",
      categoria_1: "1",
      categoria_2: "No dis",
      categoria_3: "No dis"
    },
    {
      partido: "24",
      Equipo_Local: "Argentina",
      Equipo_Visitante: "México",
      categoria_1: "No dis",
      categoria_2: "2",
      categoria_3: "No dis"
    },
    {
      partido: "13",
      Equipo_Local: "Polonia",
      Equipo_Visitante: "Argentina",
      categoria_1: "No dis",
      categoria_2: "2",
      categoria_3: "3"
    }
  ];

Features

  1. All objects in both arrays include the properties: "partido", "category_1", "category_2", "category_3", but can include more properties.
  2. The Listed properties change their values dynamically.

My starting point is to store each listed property in independent variables.

On the next line, pass as arguments the arrays where I want to find and match the specifics keys. Start with "partido" property searching in both arrays for the first match, if it finds the match or matches, it returns a new array of objects with the matches found for that property.

Start by looping through each objects in userData and dataCollection arrays. In this case, I search for matches using each key in both object arrays. And I get two matches partido: "8" and partido: "13", then store that matches inside the new variable named matchPartido array and return matchPartido.

  const checkPartido = ["partido"]
  const checkCategoria_1 = ["categoria_1"]
  const checkCategoria_2 = ["categoria_2"]
  const checkCategoria_3 = ["categoria_3"]

function getMatches(
  first,
  second,
  checkPartido,
  checkCategoria_1,
  checkCategoria_2,
  checkCategoria_3) {

  let finalMatches = []
  let matchPartido = []
  let matchCat_1 = []
  let matchCat_2 = []
  let matchCat_3 = []

  first.forEach((userMatch) => {
    second.forEach((collection) => {
      const isMatchPartido = checkPartido.every((key) => {
        return collection[key] === userMatch[key];
      });
      if (
        isMatchPartido &&
        !matchPartido.find((match) => match === userMatch)
      ) {
        matchPartido.push(userMatch);
      }
    });
  });

Now I go for the next match, which is category_1, categoria_2 and categoria_3 properties stored in the variables named checkCategory_1, checkCategory_2, checkCategory_3.

  matchPartido.forEach((userMatch) => {
    second.forEach((newCollection) => {
      const isMatchCategory = checkCategoria_1.every((key) => {
        return newCollection[key] === userMatch[key]
      });
      if (
        isMatchCategory &&
        !matchCat_1.find((match) => {
          return match === userMatch
        })
      ) {
        matchCat_1.push(userMatch)
        //console.log(matchCat_1)
        return matchCat_1
      }
    });
  });

  matchCat_1.forEach((userMatch) => {
    second.forEach((newCollection) => {
      const isMatchCategory = checkCategoria_2.every((key) => {
        return newCollection[key] === userMatch[key]
      });
      if (
        isMatchCategory &&
        !matchCat_2.find((match) => {
          return match === userMatch
        })
      ) {
        matchCat_2.push(userMatch)
        //console.log(matchCat_2)
        return matchCat_2
      }
    });
  });

  matchCat_2.forEach((userMatch) => {
    second.forEach((newCollection) => {
      const isMatchCategory = checkCategoria_3.every((key) => {
        return newCollection[key] === userMatch[key]
      });
      if (
        isMatchCategory &&
        !matchCat_3.find((match) => {
          return match === userMatch
        })
      ) {
        matchCat_3.push(userMatch)
        //console.log(matchCat_3)
        return matchCat_3
      }
    });
  });

  return (finalMatches = [...matchCat_1, matchCat_2, matchCat_3])
}
console.log(
  getFirstMatches(
    userData,
    collectionData,
    checkPartido,
    checkCategoria_1,
    checkCategoria_2,
    checkCategoria_3
  )
)

That's work OK... BUT.

I need to return an array of matched for partido 8

Now i have one match for `partido:"8"`, I mean only one user pick `partido: "8"` then check if categoria_1 property match, if not go categoria_2 and last categoria_3, there is one match categoria_1 property and return the array like the following.
[
{
user_name: "Tania"
email: "user-1@gmail.com"
partido: "8"
categoria_1: "1"
},{},{}...
]

Then for partido 24

Now i have one match for `partido:"24"`, I mean only one user pick `partido: "24"` then check if categoria_1 property match, if not, go categoria_2 and last categoria_3, there is one match categoria_2 property and return the array like the following.
[
{
user_name: "Jean"
email: "user-2@gmail.com"
partido: "24",
categoria_2: "2",
},{},{}...
]

And last for partido 13

Now i have two matches for `partido:"13"`, I mean two users pick `partido: "13"` then check if categoria_1 property match, if not go categoria_2 and last categoria_3, there is two matches categoria_2 and categoria_3 properties and return the array like the following.
[
{
user_name: "Vania",
email: "user-1@gmail.com",
partido: "13",
categoria_3: "3"
},
{
user_name: "Rick",
email: "user-1@gmail.com",
partido: "13",
categoria_2: "2"
},
,
{
user_name: "Rick",
email: "user-1@gmail.com",
partido: "13",
categoria_3: "3"
},
{}, {}, {}...
]
Omar Giancarlo
  • 119
  • 1
  • 11

2 Answers2

1

Maybe you're looking for something like a modified 'group by'? Here reducing collectionData and aggregating matching results from userData by relevant partido and cateoria_ into the result object.

const userData = [{ user_name: "Tania", email: "user-1@gmail.com", partido: "8", categoria_1: "1", categoria_2: "2", categoria_3: null }, { user_name: "Jean", email: "user-2@gmail.com", partido: "24", categoria_1: null, categoria_2: "2", categoria_3: null }, { user_name: "Vania", email: "user-4@gmail.com", partido: "13", categoria_1: null, categoria_2: "2", categoria_3: null }, { user_name: "Rick", email: "user-4@gmail.com", partido: "13", categoria_1: "1", categoria_2: "2", categoria_3: "3" }];
const collectionData = [{ partido: "8", Equipo_Local: "Argentina", Equipo_Visitante: "Arabia Saudí", categoria_1: "1", categoria_2: "No dis", categoria_3: "No dis" }, { partido: "24", Equipo_Local: "Argentina", Equipo_Visitante: "México", categoria_1: "No dis", categoria_2: "2", categoria_3: "No dis" }, { partido: "13", Equipo_Local: "Polonia", Equipo_Visitante: "Argentina", categoria_1: "No dis", categoria_2: "2", categoria_3: "3" }];

const result = Object.values(
  collectionData.reduce((res, { partido, ...rest }) => {
    res[partido] ??= { partido, ...rest, userData: {} }

    for (const cat of ['categoria_1', 'categoria_2', 'categoria_3']) {
      if (rest[cat] !== 'No dis') {
        (res[partido].userData[cat] ??= [])
          .push(...userData
            .filter(u => u.partido === partido && u[cat] === rest[cat])
            .map(u => ({ ...u }))
          )
      }
    }
    return res;
  }, {})
);

console.log(result)
pilchard
  • 12,414
  • 5
  • 11
  • 23
  • this pretty much what I'm looking for, but I don't undertand your code. And I don't want just copy and paste. I'm wonder if it possible to explain line by line your code. Thanks in advance. – Omar Giancarlo Oct 16 '22 at 23:08
  • 1
    I can add explanation later today, but you can also read over the linked group-by question, [How can I group an array of objects by key?](https://stackoverflow.com/questions/40774697/how-can-i-group-an-array-of-objects-by-key) ,which offers some insight as well as [What is the most efficient way to deep clone an object in JavaScript?](https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript) which is what the final `.map(u => ({ ...u }))` is doing to avoid storing references of grouped objects. – pilchard Oct 17 '22 at 07:48
  • Testing my app, and I get a warning in this line `res[partido] ??= { partido, ...rest, userData: {} }` SyntaxError: Unexpected token '??=' but only when deploy in a real server, locally there is no warning. – Omar Giancarlo Oct 17 '22 at 16:55
  • 1
    Seems [logical nullish assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_nullish_assignment) isn't supported by whatever version of node is being used on the server. You can replace it with an OR short circuit. `res[partido] || (res[partido] = { partido, ...rest, userData: {} })`, and the same with the second usage `(res[partido].userData[cat] || (res[partido].userData[cat] = []))` – pilchard Oct 17 '22 at 20:10
0

function findMatching(
    users, collections, matchingKeys
) {
    return users.filter(user =>
        collections.some(col =>
            matchingKeys.every(key => user[key] === col[key])
        )
    )
}

function getMatches(
    users,
    collections,
    checkPartido,
    checkCategoria_1,
    checkCategoria_2,
    checkCategoria_3) {

    let matchPartido = findMatching(users, collections, checkPartido);
    let matchCat_1 = findMatching(matchPartido, collections, checkPartido);
    let matchCat_2 = findMatching(matchCat_1, collections, checkPartido);
    let matchCat_3 = findMatching(matchCat_2, collections, checkPartido);
    let finalMatches = [matchCat_1, matchCat_2, matchCat_3]
    
    return finalMatches;
}
console.log(
    getMatches(
        userData,
        collectionData,
        ["partido"],
        ["categoria_1"],
        ["categoria_2"],
        ["categoria_3"],
    )
)
Dimava
  • 7,654
  • 1
  • 9
  • 24