0

I have a function that will check a serialized form data if there are duplicates values in it.

    s = $('#multiselectForm').serialize();
    var x = [];
    var y = [];
    x = s.split("&");
    for (var i = x.length - 1; i >= 0; i--) {
        y.push(x[i].split("="));
    };
    var c = 0;
    var e = 0;
    for (var i = y.length - 1; i >= 0; i--) {
        if (y[i][1] == y[c][1]) {
            e++;
            $('.duplicateAlert').show();
        } else {
            $('.duplicateAlert').hide();
        };
        c++;
    };

Basically, what it does is split the string produced by the serialize() function and push the data into arrays.

The array I'm trying to parse looks like this:

Array [
    Array [
    0: 'my_field1',
    1: 'val1'
    ],

    Array [
    0: 'my_field2'
    1: 'val2'
    ],

    Array [
    0: 'my_field3'
    1: 'val1'
    ]
]

Are there any better ways to do the same task? Maybe even shorter?

Burning Crystals
  • 1,157
  • 3
  • 19
  • 35

3 Answers3

2
  1. Create an empty array to hold the matches
  2. Loop through the array. On each iteration...
    1. Loop through the matches array and check if an item with the same value exists. If it does, set the matched flag.
    2. Check if the matched flag has been set
      1. if so, alert the user
      2. if not add the item to matches.

var array = [
    [ 'my_field1', 'val1' ],
    [ 'my_field2', 'val2' ],
    [ 'my_field3', 'val1' ],
    [ 'my_field4', 'val2' ],
    [ 'my_field5', 'val3' ]
], matches = [], match = false;

for(var i = 0, j = array.length; i < j; i++) {
    match = false;
    for(var k = 0, l = matches.length; k < l; k++) {
        if(matches[k][1] == array[i][1]) {
            match = true;
        }
    }
    if(match) alert('Duplicate!');
    else matches.push(array[i]);
}
  • you can also use a hash for matches instead of an array and it will be faster to check for single match instead of looping through all the potential matches – Nikos M. Jun 03 '15 at 11:31
1

If you have serialised data in the typical format like:

var data = 'foo=foo&bar=bar%26bar&blah=foo';

then you can check it for duplicates by getting the values between = and & and looking for dupes:

var seen = {};
var hasDupes = (data.match(/=[^&]+/g) || []).some(function(v){
    return v in seen || (seen[v] = true) && false;
});

console.log(hasDupes);  // true

The idea behind:

data.match(/=[^&]+/g) || []

is that match can return null if no matches are found, so if that happens the expression returns an empty array and the following call to some is called on the empty array (and returns false) rather than null, and hence doesn't throw the error that it would otherwise.

However, I still think it would be more efficient to check the form control values directly before serialising, rather than serialising the form then checking the result.

You can do that with a function like:

function checkDupValues(form) {
  var value,
      seen = {},
      controls = form.elements;

  for (var i=0, iLen=controls.length; i<iLen; i++) {
    // Might want to check type of control here and ignore buttons, etc.
    value = controls[i].value;

    // Ignore empty controls?
    if (value != '' && value in seen) {
      // have a duplicate value that is not ''
      alert('have dupes');

    } else {
      seen[value] = true;
    }
  }
}
RobG
  • 142,382
  • 31
  • 172
  • 209
0

Try this although its not much shorter:

var array = [
  [
    'my_field1',
    'val1'
  ],

  [
    'my_field2',
    'val2'
  ],

  [
    'my_field3',
    'val1'
  ]
]

var originals = [];
var duplicates = [];
for (a in array) {
  if (originals.indexOf(array[a][1] == -1)) {
    originals.push(array[a][1])
  } else {
    duplicates.push(array[a])
  }
}
alert('duplicates: ' + duplicates.join(', '));
omikes
  • 8,064
  • 8
  • 37
  • 50