Neeraj Wadhwa
Neeraj Wadhwa

Reputation: 737

Better way to achieve desired results for the following code

So the scenario is that I have this following array as my input:

[
  {
    "failureMessage": "failed",
    "data": {
      "statusCode": 201,
      "body": {
        "id": "14975",
        "key": "KEY-4855"
      }
    },
    "testSetName": "search"
  },
  {
    "failureMessage": null,
    "data": {
      "statusCode": 201,
      "body": {
        "id": "14975",
        "key": "KEY-4856"
      }
    },
    "testSetName": "download"
  },
  {
    "failureMessage": "failed 2",
    "data": {
      "statusCode": 201,
      "body": {
        "id": "14975",
        "key": "KEY-4857"
      }
    },
    "testSetName": "search"
  },
  {
    "failureMessage": null,
    "data": {
      "statusCode": 201,
      "body": {
        "id": "14975",
        "key": "KEY-4858"
      }
    },
    "testSetName": "download"
  },
  {
    "failureMessage": "failed",
    "data": {
      "statusCode": 201,
      "body": {
        "id": "14975",
        "key": "KEY-4859"
      }
    },
    "testSetName": "backgrounds"
  },
  {
    "failureMessage": null,
    "data": {
      "statusCode": 201,
      "body": {
        "id": "14975",
        "key": "KEY-4860"
      }
    },
    "testSetName": "backgrounds"
  }
]

the above array contains objects which hold the data regarding test cases

And I want an array like this:

[
  {
    "testSetName": "search",
    "testCases": ["KEY-4855", "KEY-4857"]
  },
  {
    "testSetName": "download",
    "testCases": ["KEY-4856", "KEY-4858"]
  },...
]

The above array contains objects and those objects hold the name of the test set(testSetName) and all the test cases which are part of this test set as testCases.

Now, my code is below:

  let results = testCasesObject.reduce(function (previousArr, currElement, currIndex) {

      if (previousArr.length === 0) {
        let obj = {testSetName: currElement.testSetName, testCases: []};
        obj.testCases.push(currElement.data.body.key);
        previousArr.push(obj);
      }
      else {
        let isAdded = false;
        for (let index = 0; index < previousArr.length; index += 1) {
          if (previousArr[index].testSetName === currElement.testSetName) {
            previousArr[index].testCases.push(currElement.data.body.key);
            isAdded = true;
          }
        }
        if (!isAdded) {
          let obj = {testSetName: currElement.testSetName, testCases: []};
          obj.testCases.push(currElement.data.body.key);
          previousArr.push(obj);
        }
      }

        return previousArr;
    }, []);

    console.log(results);

My code generates accurate results but I want to make it more efficient and I need help on this.

Upvotes: 0

Views: 60

Answers (2)

Nina Scholz
Nina Scholz

Reputation: 386660

You could group by testSetName and reduce the array with a lookup for an already inserted item.

var array = [{ failureMessage: "failed", data: { statusCode: 201, body: { id: "14975", key: "KEY-4855" } }, testSetName: "search" }, { failureMessage: null, data: { statusCode: 201, body: { id: "14975", key: "KEY-4856" } }, testSetName: "download" }, { failureMessage: "failed 2", data: { statusCode: 201, body: { id: "14975", key: "KEY-4857" } }, testSetName: "search" }, { failureMessage: null, data: { statusCode: 201, body: { id: "14975", key: "KEY-4858" } }, testSetName: "download" }, { failureMessage: "failed", data: { statusCode: 201, body: { id: "14975", key: "KEY-4859" } }, testSetName: "backgrounds" }, { failureMessage: null, data: { statusCode: 201, body: { id: "14975", key: "KEY-4860" } }, testSetName: "backgrounds" }],            
    result = array.reduce((r, { testSetName, data: { body: { key } } }) => {
        var item = r.find(o => o.testSetName === testSetName);
        if (item) {
            item.testCases.push(key);
        } else {
            r.push({ testSetName, testCases: [key] });
        }
        return r;
    }, []);
   
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

lipp
lipp

Reputation: 5936

What you want to achieve contains an algorithm often called "group by". There is a lodash implementation you can use: _.groupBy

This will give you an object indexed by "testSetName". Then you can go forward and map this to your desired structure.

const indexedByTestSetName = _.groupBy(data, item => item.testSetName)
// {search: [{testSetName: 'search', failureMessage: 'failed', data: {}}, ...]
const tests = Object.keys(indexedByTestSetName).map(key => ({
  testSetName: key,
  testCases: indexedByTestSetName[key]
)})
// [{testSetName: 'search', testCases: [{testSetName: 'search', failureMessage: 'failed', data: {}}, ...]}]

This is more efficient in terms of "lines of code", but how the performance compares is hard to guess. If you don't face millions of entries, I would not bother.

Upvotes: 1

Related Questions