Deduplicator function is failing to remove repeats on random iterations

Viewed 44

Newbie to JS. With help from a fellow dev, I have the following solution:

const data = {
  "Total_packages": {
    "package1": {
      "tags": [
        "kj21",
        "j1",
        "sj2",
        "z1"
      ],
      "expectedResponse": [{
        "firstName": "Name",
        "lastName": "lastName",
        "purchase": [{
          "title": "title",
          "category": [
            "a",
            "b",
            "c"
          ]
        }]
      }]
    },
    "package2": {
      "tags": [
        "s2",
        "dsd3",
        "mhg",
        "sz7"
      ],
      "expectedResponse": [{
        "firstName": "Name1",
        "lastName": "lastName1",
        "purchase": [{
          "title": "title1",
          "category": [
            "a1",
            "b1",
            "c1"
          ]
        }]
      }]
    },
    "package3": {
      "tags": [
        "s21",
        "dsd31",
        "mhg1",
        "sz71"
      ],
      "expectedResponse": [{
        "firstName": "Name2",
        "lastName": "lastName2",
        "purchase": [{
          "title": "title2",
          "category": [
            "a2",
            "b2",
            "c2"
          ]
        }]
      }]
    },
    "package4": {
      "tags": [
        "s22",
        "dsd32",
        "mhg2",
        "sz72"
      ],
      "expectedResponse": [{
        "firstName": "Name3",
        "lastName": "lastName3",
        "purchase": [{
          "title": "title3",
          "category": [
            "a3",
            "b3",
            "c3"
          ]
        }]
      }]
    },
    "package5": {
      "tags": [
        "s22",
        "dsd32",
        "mhg2",
        "sz72"
      ],
      "expectedResponse": [{
        "firstName": "Name4",
        "lastName": "lastName4",
        "purchase": [{
          "title": "title4",
          "category": [
            "a4",
            "b4",
            "c4"
          ]
        }]
      }]
    }
  }
}

var arrRand = genNum(data, 4);
console.log(arrRand);

function genNum(data, loop = '') {
  var list = [];
  var arrayOfTags = Object.entries(data.Total_packages).reduce((acc, [k, v]) => {
    if (v.tags) acc = acc.concat(v.tags.map(t => ({
      tag: t,
      response: v.expectedResponse
    })));
    return acc;
  }, []);

  for (var i = 0; i < loop; i++) {
    var randomIndex = Math.floor(Math.random() * arrayOfTags.length);
    var randomTag = arrayOfTags[randomIndex];
    list.push(randomTag);
  }
  return list;

  let output = list.filter((item, index) => {
    return list.filter((item2, index2) => {
      return ((item.tag === item2.tag) && (index2 < index));
    }).length === 0;
  });
  return output;
}

Goal: Write a function to pick a random "tags" value and its respective "expectedResponse" value.

It works well most of the time, however, when I am doing iterations of around 6-8 times (with a list that contains three times as many "tags" values), I am getting duplicates.

In my code, I am declaring a variable that is then set to the variable that contains the final list of the sanitized data. I then iteratively call that data by index (i.e arrRand[1]), and use it to validate. This is where I see the issue.

1 Answers

To avoid getting duplicate tags, we use a couple of .reduce() calls to return only unique tags.

Once the array of tags is generated, we shuffle then take the first count items to avoid duplicates.

The shuffle() function used here is a basic Fisher–Yates / Knuth shuffle.

const data = { "Total_packages": { "package1": { "tags": [ "kj21", "j1", "sj2", "z1" ], "expectedResponse": [ { "firstName": "Name", "lastName": "lastName", "purchase": [ { "title": "title", "category": [ "a", "b", "c" ] } ] } ] }, "package2": { "tags": [ "s2", "dsd3", "mhg", "sz7" ], "expectedResponse": [ { "firstName": "Name1", "lastName": "lastName1", "purchase": [ { "title": "title1", "category": [ "a1", "b1", "c1" ] } ] } ] }, "package3": { "tags": [ "s21", "dsd31", "mhg1", "sz71" ], "expectedResponse": [ { "firstName": "Name2", "lastName": "lastName2", "purchase": [ { "title": "title2", "category": [ "a2", "b2", "c2" ] } ] } ] }, "package4": { "tags": [ "s22", "dsd32", "mhg2", "sz72" ], "expectedResponse": [ { "firstName": "Name3", "lastName": "lastName3", "purchase": [ { "title": "title3", "category": [ "a3", "b3", "c3" ] } ] } ] }, "package5": { "tags": [ "s22", "dsd32", "mhg2", "sz72" ], "expectedResponse": [ { "firstName": "Name4", "lastName": "lastName4", "purchase": [ { "title": "title4", "category": [ "a4", "b4", "c4" ] } ] } ] } } } 
 
function shuffle(arr) {
  for (let i = arr.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [arr[i], arr[j]] = [arr[j], arr[i]];
  }
  return arr;
}

function genNum(data, count) {
  const uniqueTags = Object.values(Object.values(data.Total_packages).reduce((acc, v) => {
    return (v.tags || []).reduce((acc, tag) => {
      acc[tag] = acc[tag] || { tag, response: v.expectedResponse };
      return acc;
    }, acc)
  }, []));

  return shuffle(uniqueTags).slice(0, count);
}

var arrRand = genNum(data, 4);
console.log(arrRand);
.as-console-wrapper { max-height: 100% !important; }

Related