0

I've got two arrays: model and workModel and each of them contains a values array. Before sending POST request, I want to check which values have been updated.

dataToUpdate(workModel: Data[]) {
        let data: Data[];
        this.model.forEach(m => {
            m.values.forEach(val => {
                
                workModel.forEach(wm => {
                    wm.values.forEach(wval => {
                        if (val.colId != wval.colId) {
                            data.push(wm);
                        }
                    });
                });
            });
        });

        return data;
    }

is there a faster way to do that?

example of the array:

 "model": [
        {
          "values": [
            {
              "colId": 1,
              "value": 7086083333.333333
            },
            {
              "colId": 2,
              "value": null
            },
            {
              "colId": 3,
              "value": null
            }
          ],
          "rowId": 0,
        },
        {
          "values": [
            {
              "colId": 1,
              "value": null
            },
          ],
          "rowId": 1,
          "rowHeader": ""
        },
        {
          "values": [
            {
              "colId": 1,
              "value": null
            },
            {
              "colId": 2,
              "value": null
            },
            {
              "colId": 3,
              "value": null
            }
          ],
          "rowId": 2,
          "rowHeader": ""
        }
      ]

1
  • 1
    Can you give a sample of what your data looks like? It's hard to give a good answer if we have to reverse engineer the shape of the objects from nested loops. Commented Sep 19, 2019 at 7:06

1 Answer 1

1

Making some assumptions about your data you could do something like this. Let me know if it doesn't work.

Basically flatMap both arrays into a single array of values then filter over them and dedupe it.

function dataToUpdate(workModel: Data[]) {
    return workModel
        .flatMap((wm) => wm.values)
        .concat(this.model.flatMap((m) => m.values))
        .filter((val, i, arr) => {
            return arr.findIndex((v) => v.colId === val.colId) === i;
        });
}

You can also do something like this which is faster for extremely big arrays.

function dataToUpdate(workModel: Data[]) {
    const flat = workModel.flatMap((wm) => wm.values).concat(this.model.flatMap((m) => m.values));
    const uniqIds = new Set(flat.map((col) => col.colId));
    return flat.filter(uniqIds.delete)
}
Sign up to request clarification or add additional context in comments.

5 Comments

This is going to run in O(n^2) time - I doubt it's much faster than what OP has.
noob question, is map and flatMap same, flatMap gives error 'Property 'flatMap' does not exist on type 'any[]'.ts(2339) ' and I've added array example
try adding "esnext" to your lib array in tsconfig let me know if this helps (also add a polyfill for older browsers if you're doing this on the web). You can read more about flatMap here. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
@user122222 TS might not be configured to recognise new JS features. flatMap is quite new - post ES6. It's a map operation coupled with "flattening the result, e.g., you have [1, 2, 3] and .map(x => [x*2]) would give you [[2], [4], [6]] while .flatMap(x => [x*2]) will keep the array at one level - [2, 4, 6].
No problem, some slightly related advice for the future to avoid for loops in general is that all Array based algorithms can actually be solved using only Array.prototype.reduce and flatMap, concat, map, filter are just syntax sugar for using reduce easier.

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.