ReynierPM ReynierPM - 26 days ago 12
Javascript Question

How don't allow duplicates in the items array when condition and field name are the same?

I have this piece of HTML code:

<select id="table" name="table">
<option></option>
<option value="asset_locations">Asset Locations</option>
<option value="companies">Company</option>
</select>
<select id="fields" name="fields">
<option></option>
<option value="asset_locations_id">asset_locations_id</option>
<option value="companies_id">companies_id</option>
<option value="region_id">region_id</option>
<option value="asset_locations_name">asset_locations_name</option>
...
</select>
<select id="conditions">
<option></option>
<option value="=">Equal to</option>
<option value="<>">Not Equal to</option>
<option value=">">Greater Than (Strictly)</option>
...
</select>
<select id="condition_value_1" multiple="multiple" style="display: none">
<option></option>
</select>
<button id="add" style="display: none">Add</button>


And I am building an object as follow:

$(function() {
...
var list = {};
var items = [];
...

$('#add').click(function() {
var data_field = $('#fields :selected').val();
var data_condition = $('#conditions :selected').val();
var data_values = $('#condition_value_1').val();

var item = [
data_field,
data_condition,
data_values
];

var key = JSON.stringify(item);
if (list[key] === 1) return; // skip

list[key] = 1;
items.push(item);

console.log(list);
console.log(items);
});
});


It works but it allow duplicates for
data_field
and
data_condition
meaning they should be unique and update it's
data_values
only. For example, if you execute the code above and add some values for a given condition you should end with the following at the console:

Object {["asset_locations_name","=",["1212341047","1212341048","1212369641"]]: 1}


Now if you run it for a second time and change the
data_values
you will end with the following at the console:

Object {["asset_locations_name","=",["1212341047","1212341048","1212369641"]]: 1, ["asset_locations_name","=",["1212341047","1212341048","1212369653"]]: 1}


As you notice both
data_field
and
data_condition
are the same an even they share idem values only one is different. A correct output should be:

Object {["asset_locations_name","=",["1212341047","1212341048","1212369641", "1212369653"]]: 1}


Where the
data_values
gets updated with new values and the
data_field
and
data_condition
keeps unique.

The conditions on second+ execution in this cases would be:


  • if
    data_field
    and
    data_condition
    remain the same then look for it's values and update them properly without allow duplicates.

  • other than that will be a valid option to add a new entry.



Here is another example from the above:

1st exec:
input: asset_locations_name, in, ["1212341047","1212341048","1212369641"]
output: Object {["asset_locations_name","=",["1212341047","1212341048","1212369641"]]: 1}

2nd exec:
input: asset_locations_name, in, ["1212341047","1212341048","1212369653"]
output: Object {["asset_locations_name","=",["1212341047","1212341048","1212369641", "1212369653"]]: 1}

3rd exec:
input: asset_locations_name, not in, ["1212341047","1212341048","1212369653"]
output: Object {["asset_locations_name","=",["1212341047","1212341048","1212369641"]]: 1, ["asset_locations_name","<>",["1212341047","1212341048","1212369653"]]: 1}


Notice how in the
2nd
exec I keep the same entry but updating it's
data_values
which is the right and wanted behavior.

Notice how in the
3rd
exec we are changing the value of the
data_condition
making it to be a new entry no matter if the
data_values
are the same. If there is any typo and I am not aware or you didn't understand anything let me know and I try to do my best to get this clear.


Note: the solution should be compatible with older browser. (We're updating but until then I need to use old browser compatibility)


I leave a working Fiddle here.

How can I achieve this? Any help?

Answer

This is an ideal situation to use an ES6 Map. But as you are asking for backwards compatibility, I will suggest this:

var items = {};


//...
var key = JSON.stringify([data_field, data_condition]); // only these two!

items[key] = item; // will overwrite if same key

// if you need to have it as an array:
for (key in items) {
    console.log(items[key]);
}
// ...

Your updated fiddle. I also included a function if you ever need to convert this items object to a plain array.