1

Given the following array (nested), I'm unsure how to loop through these nested arrays using map to produce the below result.

const qry = [
  {
    qryNm: "A",
    qryResult: "",
    qryWhere: [
        {
            qryReqs: [
                {
                    col: "name",
                    op: "=",
                    colVal: "tom"
                },
                {
                    col: "country",
                    op: "=",
                    colVal: "germany"
                }   
            ]
        },
        {
            qryReqs: [
                {
                    col: "name",
                    op: "=",
                    colVal: "sally"
                },
                {
                    col: "country",
                    op: "=",
                    colVal: "italy"
                }   
            ]
        }        
    ]
  },
  {
    qryNm: "B",
    qryResult: "",
    qryWhere: [
        {
            qryReqs: [
                {
                    col: "name",
                    op: "=",
                    colVal: "kirk"
                },
                {
                    col: "country",
                    op: "=",
                    colVal: "sweeden"
                }   
            ]
        },
        {
            qryReqs: [
                {
                    col: "name",
                    op: "=",
                    colVal: "grace"
                },
                {
                    col: "country",
                    op: "=",
                    colVal: "usa"
                }   
            ]
        }        
    ]
  }
]

I need to loop through the above array and produce the following result:

(name = 'tom' and
 country = 'germany')
or
(name = 'sally' and
 country = 'italy')

and assign this value to qryResult within the qry array, for that qryNm, i.e.:

qryResult = "(name = 'tom' and country = 'germany') or (name = 'sally' and country = 'italy')";

Obviously, this qryResult will need to be processed for every array element within the qry array.

So for every qryReqs within the array qryWhere, break this as an "OR" condition.

Having the three level of arrays, I'm unsure how to achieve my result.

I realise that I need to use:

qry.map((q, i) => (
  // unsure from here
))

Any help/guidance would be great.

2 Answers 2

2

You can break the problem down into parts. First, you need to turn the below object (req):

{col: "name", op: "=", colVal: "sally"}

into the string:

name = 'sally'

This can be done by using a template literal (or string concatenation) and by accessing the col, op and colVal properties from your object:

`${req.col} ${req.op} '${req.colVal}'`

Now that you can convert the individual objects into strings you can map your innermost (qryReqs) array using the above template literal:

qryReqs: [ 
  { col: "name", op: "=", colVal: "sally" }, 
  { col: "country", op: "=", colVal: "italy" } 
]

The mapping function for this would look something like:

qryReqs.map(req => `${req.col} ${req.op} '${req.colVal}'`)

This produces an array of strings:

["name = 'sally'", "country = 'italy'"]

In your output, you want this to be in the form of: (string[0] and string[1] and string[2] and ... and string[n]). We can join the strings in this array using .join(' and ') to get a string, and then wrap that string in parenthesis ():

`(${qryReqs.map(req => `${req.col} ${req.op} '${req.colVal}'`).join(' and ')})`

Doing this gives us a string joined with "and"s for each inner object wrapped in parenthesis:

"(name = 'sally' and country = 'italy')"

Since we want to perform the above mapping operation on all of your objects inside of qryWhere, we can map qryWhere and apply the above template literal + join() logic to each object:

qryWhere.map(
  ({qryReqs}) => `(${qryReqs.map(req => `${req.col} ${req.op} '${req.colVal}'`).join(' and ')})`
)

Doing the above gives us:

["(name = 'tom' and country = 'germany')", "(name = 'sally' and country = 'italy')"]

With this result, we need to join them together with an "or" clauses to match your output, which can be done by joining the above array of results with .join(" or "):

qryWhere.map(
  ({qryReqs}) => `(${qryReqs.map(req => `${req.col} ${req.op} '${req.colVal}'`).join(' and ')})`
).join(' or ')

You can then perform an outer .map() on your qry array to perform this conversion for all objects in your array:

const qry = [{ qryNm: "A", qryWhere: [{ qryReqs: [{ col: "name", op: "=", colVal: "tom" }, { col: "country", op: "=", colVal: "germany" } ] }, { qryReqs: [{ col: "name", op: "=", colVal: "sally" }, { col: "country", op: "=", colVal: "italy" } ] } ] }];

const results = qry.map(({qryWhere}) => qryWhere.map(
  ({qryReqs}) => `(${qryReqs.map(req => `${req.col} ${req.op} '${req.colVal}'`).join(' and ')})`
).join(' or '));
const [res] = results; // if you want to extract the first result

console.log(results);
console.log(res);

If you want to add an additional property qryResult to your objects, this can be done by creating a new object {} in your map callback, and then using the spread syntax ... to copy all the (enumerable own) keys from the current object to the new object. You can then add the new qryResult to the new object with the value of the above mapping:

const qry = [{ qryNm: "A", qryWhere: [{ qryReqs: [{ col: "name", op: "=", colVal: "tom" }, { col: "country", op: "=", colVal: "germany" } ] }, { qryReqs: [{ col: "name", op: "=", colVal: "sally" }, { col: "country", op: "=", colVal: "italy" } ] } ] }];

const result = qry.map((qryObj) => ({
  ...qryObj,
  qryResult: qryObj.qryWhere.map(
    ({qryReqs}) => `(${qryReqs.map(req => `${req.col} ${req.op} '${req.colVal}'`).join(' and ')})`
  ).join(' or ')
}));

console.log(result);
console.log(result[0].qryResult);

Sign up to request clarification or add additional context in comments.

5 Comments

As per comment above: After thinking further about the result, decided that it would more beneficial to store it as part of the qry array, within qryResult. Unsure how this can be achieved as part of your solution as there will be multiple qry array elements.
@ArthurJ I have updated my answer so that it adds an additional property qryResult
Nick, I updated my scenario above to include two queries, qryNm A and qryNm B so apologies for not including another query within my example but I basically require now is two separate qryResult values on a per qryNm basis. Using your second solution, is there a means of just pulling out the qryResult for each query without hardcoding the array index of result[0] and result[1] as part of your solution?
@ArthurJS How do you want to pull out the query though if you don't explicitly reference it? You can loop over your results array: results.forEach(query => console.log(query.qryResult)); that will log all the qryResults, but I'm not sure if that is what you want? Or do you want to be able to do something like results.A.qryResult, so in that case results is an object?
All good Nick - managed to achieve what I was after based on your second solution.
2

Here is one way to achieve a similar result

const qry = [{
  qryNm: 'A',
  qryWhere: [{
      qryReqs: [{
          col: 'name',
          op: '=',
          colVal: 'tom',
        },
        {
          col: 'country',
          op: '=',
          colVal: 'germany',
        },
      ],
    },
    {
      qryReqs: [{
          col: 'name',
          op: '=',
          colVal: 'sally',
        },
        {
          col: 'country',
          op: '=',
          colVal: 'italy',
        },
      ],
    },
  ],
}, ]

const result = qry
  .map(obj1 =>
    obj1.qryWhere
    .map(
      obj2 =>
      `( name = '${obj2.qryReqs[0].colVal}' and country = '${obj2.qryReqs[1].colVal}' )`
    )
    .join(' or ')
  )
  .join(' or ')

console.log(result)

1 Comment

After thinking further about the result, decided that it would more beneficial to store it as part of the qry array, within qryResult. Unsure how this can be achieved as part of your solution as there will be multiple qry array elements.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.