Compare Object Ids from Array in JavaScript - javascript

I got an array with some objects. Each object has an id. So when generating a new id, I want to check if an object with this id already exists. If there is an equal id, a new one should be generated.
generateId() {
var records = store.getRecords(); // get all the objects
var newId = getNewId(); // calculate a new id
if (record.id == newId) // id already exists // record.id = id of the object
newId = generateId(); // generate a new id
else
return newId; // return the id
}
getNewId() {
// generate Id...
}
So how can I check all my records here if (record.id == newId) ? I use JQuery.

You can use a simple for loop for simlicity, it might not be efficient if you've got a lot of records obtained. If the structure of the object is the same for all records and assuming the data type of the object value matches the newId variable, this function will serve the purpose.
function DoesExist() {
for(var i = 0; i < records.length; i++) {
if(records[i].id == newId)
return true;
}
return false;
}

The way I would go about it is to split my logic into multiple functions, so that I can check any new id against the existing ones. Then, wrapping this inside a loop, I could check generated values until one is found that is not in the array. For example (methods and values added for testing):
function generateId() {
var records = store.getRecords(); // get all the objects
var newId;
var isUnique = false;
while (!isUnique) { // check if unique, repeatedly
newId = getNewId(); // calculate a new id
isUnique = checkId(newId);
}
return newId; // return the id (is unique)
}
// Check if the id is unique against existing records
function checkId(newId) {
var records = store.getRecords();
for (var key in records)
if (records[key].id == newId)
return false;
return true;
}
// Added for testing
function getNewId() {
return Math.round(Math.random() * 10);
}
var store = {getRecords: function() {return [{id: 1}, {id: 2}, {id: 4}, {id: 6}];}}
// Actual testing
console.log(generateId());

this should work as incremental id generator:
const data = [{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6}];
const exists = id => data.some(o => o.id === id);
const newId = (start = 0) => {
const id = ++start;
return exists(id) ? newId(id) : id;
};
// you can also evaluate to implement some uid logic...
// there isn't much you can do on the client, but,
// this could also help
const newUID = () => {
const uid = Math.random().toString(32).substr(2);
return exists(uid) ? newUID() : uid;
}
console.log({
incrementalID: newId(),
UID: newUID()
});

Related

Prevent element from being added based on boolean

I have an array of ID's ("world") to iterate. If the world element value exists as myArray[n].id then I want to delete the entire element in myArray. If not, then I want to add it to myArray.
world = ["12424126","12461667","12492468","12761163"]
myArray = [
{"id": "12424126"},
{"id": "12761163"},
{"id": "12492468"}
]
Example: if the first element in world[n] ("12424126") exists in myArray as {"id": "12424126"} then delete the element {"id": "12424126"}
if the first element in world[n] ("12424126") does not exists in myArray, then
myArray.push ({"id":world[n]});
}
for (n = 0; n <= world.length; n++) {
ID = world[n];
finished = false;
if (myArray.find(x => x.id === ID)) {
var index = _.findIndex(myArray, { "id": ID });
if (index > -1) { myArray.splice(index, 1);
finished = true;}
}
if (!finished) // PROBLEM: THE RECORD IS ADDED REGARDLESS OF FINISHED T/F
{myArray.push ({id:ID }); // HOW CAN I FIX THIS ?
}
}
The following code works as you want
world = ["12424126", "12461667", "12492468", "12761163"];
myArray = [{ id: "12424126" }, { id: "12761163" }, { id: "12492468" }];
for (n = 0; n < world.length; n++) {
ID = world[n];
var index = myArray.findIndex((item) => item.id == ID);
if (index > -1) {
myArray.splice(index, 1);
} else {
myArray.push({ id: ID });
}
}
The problem is that your loop will make finished turn from true to false again in a next iteration of the loop. You would need to exit the loop immediately when finished is set to true.
However, this can be better solved with a Set:
const world = ["12424126","12461667","12492468","12761163"];
let myArray = [{"id": "12424126"},{"id": "12761163"},{"id": "12492468"}];
const set = new Set(myArray.map(({id}) => id).concat(world));
myArray = Array.from(set, id => ({id}));
console.log(myArray);
If you don't want to assign to myArray a new array, and not create new objects for those that already existed in the array, then:
const world = ["12424126","12461667","12492468","12761163"];
let myArray = [{"id": "12424126"},{"id": "12761163"},{"id": "12492468"}];
const set = new Set(myArray.map(({id}) => id).concat(world));
myArray.push(...Array.from(set).slice(myArray.length).map(id => ({id})));
console.log(myArray);
This second solution assumes however that myArray did not already have duplicate id values.

Add only unique objects to array

I have object created by function:
$scope.checkPosRole = function(possition , posRole , posFunction) {
var rolePos = {pos: possition, posRole: posRole, posFunction: posFunction};
$scope.rolePossition.push(rolePos);
};
The problem is that I want to in the array was only 1 object with the specified value of pos. In the case when the object is added with value pos that exists already in the array I want to swap new object with object exist already in array.
I've tried every function call scan the tables with foreach, but did not bring me desirable effect. Please help.
try this
var rolePosition = [{ id: 1}, {id: 2}, {id: 3}];
function addRolePosition(data) {
var index = -1;
for(var i = 0, i < rolePosition.length; i++) {
if(rolePosition[i].id === data.id) {
index = i;
}
}
if(index > -1) {
rolePosition[index] = data;
} else {
rolePosition.push(data)
}
}

Merge array of javascript objects by property key

First of all: I already found this thread, which basically is exactly what I want, but I tried my best to apply it to my needs - I couldn't.
So, I have the following javascript function:
function loadRelationData(object) {
var result = [];
var parents = []
parents = getParentObjectsByObjectID(object['ObjectID']);
var tmpFirstObjects = [];
var tmpOtherObjects = [];
$.each(parents, function (_, parent) {
var keyName = 'Übergeordnete ' + parent['ObjectType'];
var pushObject = {};
if (parent['ObjectType'] == object['ObjectType']) {
pushObject['Fieldname'] = keyName;
pushObject['Value'] = parent['Name'];
tmpFirstObjects.push(pushObject);
} else {
pushObject['Fieldname'] = keyName;
pushObject['Value'] = parent['Name'];
tmpOtherObjects.push(pushObject);
}
});
result = result.concat(tmpFirstObjects).concat(tmpOtherObjects);
return result;
}
The parents array looks like this
And my function creates this result
This might be a bit complicated, but I need to split it up like this, because I need the order.
What I want is an array with both "TEC_MapLocations" joined together like this:
[
{Fieldname: 'Übergeordnete TEC_Equipment', Value: 'E0192'},
{Fieldname: 'Übergeordnete TEC_MapLocation', Value: ['M100', 'M200']},
{Fieldname: 'Übergeordnete TEC_FunctionalLocation', Value: 'FL456'}
]
Any ideas on how to alter my code to achieve the desired result right away or how to merge the results array?
edit: I used Joseph's solution and used the following (quick and dirty) sort function to get back my desired sorting:
output.sort(function (a, b) {
if (a.ObjectType == object.ObjectType) {
return -1
} else {
return 1
}
});
What you'd want to do first is build a hash with Fieldname as key, and an array as value. Then you'd want to use reduce to add the values into the hash and array. Then you can transform it into an array using Object.keys and map.
var input = [
{Name: 'M100', ObjectID: 1, ObjectType: 'TEC_MapLocation'},
{Name: 'M200', ObjectID: 2, ObjectType: 'TEC_MapLocation'},
{Name: 'FL456', ObjectID: 4, ObjectType: 'TEC_FunctionalLocation'},
{Name: 'E0192', ObjectID: 5, ObjectType: 'TEC_Equipment'}
];
var hash = input.reduce(function(carry, item){
// Create the name
var name = 'Übergeordnete ' + item.ObjectType;
// If array with name doesn't exist, create it
if(!carry[name]) carry[name] = [];
// If item isn't in the array, add it.
if(!~carry[name].indexOf(item.Name)) carry[name].push(item.Name);
return carry;
}, {});
// Convert the hash into an array
var output = Object.keys(hash).map(function(key, index, array){
return { Fieldname: key, Value: hash[key] }
});
document.write(JSON.stringify(output));
Try this:
function joinObjects( array ) {
// Start with empty array
var ret = new Array();
// Iterate array
for ( var i = 0; i < array.length; i++ ) {
// Search by fieldname
var match = false;
var j;
for ( j = 0; j < ret.length; j++ ) {
if ( array[i].Fieldname == ret[j].Fieldname ) { match = true; break; }
}
// If not exists
if ( !match ) {
// Intert object
ret.push({
Fieldname: array[i].Fieldname,
Value: new Array()
});
}
// Insert value
ret[j].Value.push( array[i].Value );
}
// Return new array
return ret;
}
http://jsfiddle.net/6entfv4x/

Find and update a hash by HashKey to add record for saving

Lets say I have an array of hashes:
hash = [{"one": 1}, {"two": 2}]
And I want to find a hash and add to it. For example find "one" and add:
hash = [{"one": 1, "new": new}, {"two": 2}]
I could do this by hash key? If so how would I do it? Or is there a much better way to do this thing in Javascript? I dont want to copy the hash, make a new one and delete the old one. Just update what is already there.
JavaScript is pretty dynamic so you should be able to do something like this:
var hash = [{"one": 1}, {"two": 2}];
var hLength = hash.length;
for(int i=0; i<hLength; i++){ // Loop to find the required object.
var obj = hash[i];
if(obj.hasOwnProperty('one')){ // Condition you're looking for
obj["new"] = "new"; // Property you wish to add.
break;
}
}
If you're happy to use underscore you could get it done by starting with:
var hashes = [{"one": 1}, {"two": 2}];
var changed = _.map(hashes, function(hash){
if(hash.one) {
hash["new"] = "new";
return hash
}
return hash;
});
You could generalise it a bit by passing a filter function to encapsulate the if statement, and another function to encapsulate the modification to the hash.
EDIT If you want to generalise what to look for in the hash, this could work:
var hashes = [{"one": 1}, {"two": 2}];
var isOne = function(hash) {
return hash.one;
}
var addNew = function(hash) {
hash["new"] = "new";
return hash;
}
var hashChanger = function(filter, editor) {
return function(hash) {
if(filter(hash)) {
return editor(hash);
}
return hash;
}
}
var changed = _.map(hashes, hashChanger(isOne, addNew));
Here is a function I just wrote to do this.
/*
* hashes - (array) of hashes
* needle - (string) key to search for / (int) index of object
* key - (string) key of new object you wish to insert
* value - (mixed) value of new object you wish to insert
*/
function addToHash(hashes, needle, key, value) {
var count = hashes.length;
// If needle is a number treat it as an array key
if (typeof needle === 'number' && needle < count) {
hashes[needle][key] = value;
return true;
} else {
// Search hashes for needle
for (var i=0; i<count; i++)
{
if (needle in hashes[i]) {
hashes[i][key] = value;
return true;
}
}
}
return false;
}

Find duplicates without going through the list twice?

I need to know if one or more duplicates exist in a list. Is there a way to do this without travelling through the list more than once?
Thanks guys for the suggestions. I ended up using this because it was the simplest to implement:
var names = [];
var namesLen = names.length;
for (i=0; i<namesLen; i++) {
for (x=0; x<namesLen; x++) {
if (names[i] === names[x] && (i !== x)) {alert('dupe')}
}
}
Well the usual way to do that would be to put each item in a hashmap dictionary and you could check if it was already inserted. If your list is of objects they you would have to create your own hash function on the object as you would know what makes each one unique. Check out the answer to this question.
JavaScript Hashmap Equivalent
This method uses an object as a lookup table to keep track of how many and which dups were found. It then returns an object with each dup and the dup count.
function findDups(list) {
var uniques = {}, val;
var dups = {};
for (var i = 0, len = list.length; i < len; i++) {
val = list[i];
if (val in uniques) {
uniques[val]++;
dups[val] = uniques[val];
} else {
uniques[val] = 1;
}
}
return(dups);
}
var data = [1,2,3,4,5,2,3,2,6,8,9,9];
findDups(data); // returns {2: 3, 3: 2, 9: 2}
var data2 = [1,2,3,4,5,6,7,8,9];
findDups(data2); // returns {}
var data3 = [1,1,1,1,1,2,3,4];
findDups(data3); // returns {1: 5}
Since we now have ES6 available with the built-in Map object, here's a version of findDups() that uses the Map object:
function findDups(list) {
const uniques = new Set(); // set of items found
const dups = new Map(); // count of items that have dups
for (let val of list) {
if (uniques.has(val)) {
let cnt = dups.get(val) || 1;
dups.set(val, ++cnt);
} else {
uniques.add(val);
}
}
return dups;
}
var data = [1,2,3,4,5,2,3,2,6,8,9,9];
log(findDups(data)); // returns {2 => 3, 3 => 2, 9 => 2}
var data2 = [1,2,3,4,5,6,7,8,9];
log(findDups(data2)); // returns empty map
var data3 = [1,1,1,1,1,2,3,4];
log(findDups(data3)); // returns {1 => 5}
// display resulting Map object (only used for debugging display in snippet)
function log(map) {
let output = [];
for (let [key, value] of map) {
output.push(key + " => " + value);
}
let div = document.createElement("div");
div.innerHTML = "{" + output.join(", ") + "}";
document.body.appendChild(div);
}
If your strings are in an array (A) you can use A.some-
it will return true and quit as soon as it finds a duplicate,
or return false if it has checked them all without any duplicates.
has_duplicates= A.some(function(itm){
return A.indexOf(itm)===A.lastIndexOf(itm);
});
If your list was just words or phrases, you could put them into an associative array.
var list=new Array("foo", "bar", "foobar", "foo", "bar");
var newlist= new Array();
for(i in list){
if(newlist[list[i]])
newlist[list[i]]++;
else
newlist[list[i]]=1;
}
Your final array should look like this:
"foo"=>2, "bar"=>2, "foobar"=>1

Categories

Resources