array difference in javascript - javascript

I know this will be so simple but I am trying this for two days so I finally decided to take help from you guys...
I have tried this probably the same question as mine but it is not giving me the answer.
ok so these are the two array
a = [{toNumber: "123", message: "Hi Deep "}, {toNumber: "321", message: "Test1"}]
b = [{toNumber: "321", message: "Test2"}, {toNumber: "123", message: "Hi Deep "}]
What I want is
diff = [{toNumber: "321", message: "Test2"}]
so quick help would be much appriciated.

So with your code you need to look at the other object and see if it has any keys that match. If it matches, you need to see if the message matches. So you can make a look up object that has the list of ids. You can than loop over your second array and see if they march.
var a = [
{toNumber: "123", message: "Hi Deep "},
{toNumber: "321", message: "Test1"}
]
var b = [
{toNumber: "321", message: "Test2"},
{toNumber: "123", message: "Hi Deep "}
]
// create the lookup from the first array
var lookup = a.reduce( function (lookUpObj, entryA) {
// set the object property with the toNumber property
lookUpObj[entryA.toNumber] = entryA.message
return lookUpObj
}, {})
// Now loop over the array and look for the differences
var diff = b.reduce(function (arr, entryB) {
// grab the entry from the lookup object we created
var orginalMessage = lookup[entryB.toNumber]
// if we do not have it listed OR the message is different
// add it to the list as changed.
if (!orginalMessage || orginalMessage !== entryB.message) {
arr.push(entryB)
}
return arr
}, [])
console.log(diff)
Now that will match any differences from a to b. If anything was removed in B that is not in A it will not be caught.

Where is the problem ???
const a =
[ { toNumber: "123", message: "Hi Deep " }
, { toNumber: "321", message: "Test1" }
]
const b =
[ { toNumber: "321", message: "Test2" }
, { toNumber: "123", message: "Hi Deep " }
]
const diff = b.filter(eB=>!a.some(eA=>( eA.toNumber===eB.toNumber
&& eA.message===eB.message )))
document.write( JSON.stringify( diff ) )

Related

Javascript How to find a complete class object in an array

I have an array of objects that I use for a materials table datasource. I need to see if this row already exists in the datasource array before adding it.
There is no key value in this array. So I need to check if all items are unique
var datasource = [
{ Name: Jon, Address: 123 something }, {Name: Tyler , Address: 333 Something}
]
var rowtoAdd = [
{ Name: Jon, Address: 123 something }
]
const found = datasource.find(x => x.name == rowtoAdd.Name && x.Address == rowtoAdd.Address)
Is there a better way?
One way you can do this is by hashing the elements. Your current solution takes O(n) time each time you need to check. if you create a hashtable it will take 0(n) to create the table but the run time will O(1) for all consecutive run.
var datasource = [
{ "Name": "Jon", "Address": "123 something" }, {"Name": "Tyler" , "Address": "333 Something"}
]
var map = datasource.reduce(function(map, obj) {
map[obj.Name+obj.Address] = true;
return map;
}, {});
rowtoAdd = { "Name": "Jon", "Address": "123 something" }
if(!map[rowtoAdd.Name+rowtoAdd.Address])
datasource.push(rowtoAdd)
So, in sort reduce your array to a hashmap

convert nested object to one level up object in javascript

given json : -
{
"_id": "5c1c4b2defb4ab11f801f30d",
"name": "Ray15",
"email": "ray15#gmail.com",
"deviceToken": "dgtssgeegwes",
"deviceType": "IOS",
"tokens": [
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1YzFjNGIyZGVmYjRhYjExZjgwMWYzMGQiLCJhY2Nlc3MiOiJhdXRoIiwiaWF0IjoxNTQ1MzU4MTI2fQ.YdK0MjOm7Lff22uTFITQdic0gKdMZRpsmRee-yejDpQ"
}
]
}
desired json: -
{
"_id": "5c1c4b2defb4ab11f801f30d",
"name": "Ray15",
"email": "ray15#gmail.com",
"deviceToken": "dgtssgeegwes",
"deviceType": "IOS",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1YzFjNGIyZGVmYjRhYjExZjgwMWYzMGQiLCJhY2Nlc3MiOiJhdXRoIiwiaWF0IjoxNTQ1MzU4MTI2fQ.YdK0MjOm7Lff22uTFITQdic0gKdMZRpsmRee-yejDpQ"
}
I want to convert JSON with the help of lodash library of npm in javascript or suggest any other library,
it might be a silly question, Please explain it properly, I am a newbie in javascript and try to learn node.js. comment me if you need more explanation.
Thanks for help
You don't really need a library, you can just assign the property and delete the other.
However tokens is an array, which suggest there might be more than one. This will only take the first one (obj.tokens[0].token). Since objects can't have duplicate keys, you will only be able to have one token with your desired format (if that matters).
let obj = {
"_id": "5c1c4b2defb4ab11f801f30d",
"name": "Ray15",
"email": "ray15#gmail.com",
"deviceToken": "dgtssgeegwes",
"deviceType": "IOS",
"tokens": [
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1YzFjNGIyZGVmYjRhYjExZjgwMWYzMGQiLCJhY2Nlc3MiOiJhdXRoIiwiaWF0IjoxNTQ1MzU4MTI2fQ.YdK0MjOm7Lff22uTFITQdic0gKdMZRpsmRee-yejDpQ"
}
]
}
obj.token = obj.tokens[0].token
delete obj.tokens
console.log(obj)
There are a number of ways to solve this problem and no one "right" way. However, you may want to consider creating a new object, rather than mutating the original object. Objects are always passed by reference in JavaScript and it's easy to accidentally modify an object inside a function, not realizing that you just changed that object everywhere else it's referenced as well.
Since you mentioned it, here is a way to solve this with Lodash.
const obj = {
"_id": "5c1c4b2defb4ab11f801f30d",
"name": "Ray15",
"email": "ray15#gmail.com",
"deviceToken": "dgtssgeegwes",
"deviceType": "IOS",
"tokens": [
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1YzFjNGIyZGVmYjRhYjExZjgwMWYzMGQiLCJhY2Nlc3MiOiJhdXRoIiwiaWF0IjoxNTQ1MzU4MTI2fQ.YdK0MjOm7Lff22uTFITQdic0gKdMZRpsmRee-yejDpQ"
}
]
};
// create a new object without the tokens property
const newObj = _.omit(obj, 'tokens');
// get the first token object from the tokens array
const tokenObj = _.head(obj.tokens);
// get the token string from the token object, defaulting to empty string if not found
newObj.token = _.get(tokenObj, 'token', '');
console.log(newObj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Lodash is a great library and used by many projects. It can be especially helpful for new developers. For example, _.head(arr) will return undefined if arr is undefined. However, arr[0] would crash in the same scenario.
Here's one way to solve it without a library.
const obj = {
"_id": "5c1c4b2defb4ab11f801f30d",
"name": "Ray15",
"email": "ray15#gmail.com",
"deviceToken": "dgtssgeegwes",
"deviceType": "IOS",
"tokens": [
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1YzFjNGIyZGVmYjRhYjExZjgwMWYzMGQiLCJhY2Nlc3MiOiJhdXRoIiwiaWF0IjoxNTQ1MzU4MTI2fQ.YdK0MjOm7Lff22uTFITQdic0gKdMZRpsmRee-yejDpQ"
}
]
};
// create a copy of the original object.
// note that Object.assign will make a shallow copy of our object,
// so newObj.tokens will be a pointer to obj.tokens.
// in this instance, we don't care, as we are going to remove newObj.tokens anyway.
const newObj = Object.assign({}, obj);
// throw away the tokens property.
// OK to mutate newObj as we know it is not used anywhere else.
delete newObj.tokens;
// get the first token object from the tokens array.
// the (expectedArray || []) pattern ensures we have an array if obj.tokens is null or undefined.
const tokenObj = (obj.tokens || [])[0];
// get the token string from the token object.
// again, using the (expectedObject || {}) pattern in case tokenObj is null or undefined.
const token = (tokenObj || {}).token;
// create a new property called "token" on our newObj object.
// set it to our token value or an empty string if token is null or undefined.
newObj.token = token || '';
// of course, if you know the tokens array will always have a valid token object,
// you can simply use newObj.token = obj.tokens[0].token.
console.log(newObj);
Using destructuring assignment with "empty" representations of your types works nicely. transform produces a reliable output when tokens contains zero, one, or many { token: ... } values.
const emptyUser =
{ _id: 0, name: "", tokens: [] }
const emptyToken =
{ token: "" }
const toSingleTokenUser =
({ tokens: [ { token } = emptyToken ], ...u } = emptyUser) =>
({ ...u, token })
console .log
( toSingleTokenUser ({ _id: 1, name: "a", tokens: [ { token: "t" } ] })
// { _id: 1, name: "a", token: "t" }
, toSingleTokenUser ({ _id: 1, name: "a", tokens: [] })
// { _id: 1, name: "a", token: "" }
, toSingleTokenUser ({ _id: 1, name: "a", tokens: [ { token: "t1" }, { token: "t2" } ] })
// { _id: 1, name: "a", token: "t1" }
, toSingleTokenUser ({ foo: "bar", tokens: [ { token: "t" } ] })
// { foo: "bar", token: "t" }
)

Sort an array of objects by different keys

Hope you can help me with this question I have, that I'm pretty sure it's simple but I feel I'm missing some basic concepts here.
I have an array of objects like
[{
"id":"123",
"creationUser":"user1",
"updateUser":null,
"creationDate":1517495569000,
"updateDate":null,
"text":"Hello World"
},
{
"id":"543",
"creationUser":"user2",
"updateUser":"user3",
"creationDate":1517912985769,
"updateDate":1517921704448,
"text":"Hello people"
},
{
"id":"847",
"creationUser":"user 4",
"updateUser":null,
"creationDate":null,
"updateDate":1517913015110,
"text":"Text 1"
},
{
"id":"344",
"creationUser":"user 1",
"updateUser":"central",
"creationDate":1517912979283,
"updateDate":1517923926834,
"text":"Aloha!"
}]
As you can see there are some objects that doesn't have been updated so those values are set to null, but others have been updated, so what I would like to do is to order that array by creation date unless it has been updated, which mean that the updatedDate is the key value to compare this array.
I have tried:
let comments = conversation.sort(
(a,b) => {
if (a.updateDate){
return (a.creationDate - b.updateDate);
} else {
return (b.creationDate - a.updateDate);
}
});
But obviously it only works when comparing non updated objects. I'm pretty sure I'm missing something but I'm not sure, I also thought on splitting the array into updated array and non updated array and then merege it, but it sounds a bit hacky to me.
Please please, if you can give me a hint on this, it would be great!
Thanks a lot!
You could use logical OR || and take as default creationDate.
var array = [{ id: "123", creationUser: "user1", updateUser: null, creationDate: 1517495569000, updateDate: null, text: "Hello World" }, { id: "543", creationUser: "user2", updateUser: "user3", creationDate: 1517912985769, updateDate: 1517921704448, text: "Hello people" }, { id: "847", creationUser: "user 4", updateUser: null, creationDate: null, updateDate: 1517913015110, text: "Text 1" }, { id: "344", creationUser: "user 1", updateUser: "central", creationDate: 1517912979283, updateDate: 1517923926834, text: "Aloha!" }];
array.sort((a, b) => (a.updateDate || a.creationDate) - (b.updateDate || b.creationDate));
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
So that make it so you use the defined dates by picking the one that is defined for each object.
var aDate = a.updateDate || a.creationDate
var bDate = b.updateDate || b.creationDate
return bDate - aDate
Evaluate the existence of the updateDate property first and if not exists, use the creationDate property:
var data =[{
"id":"123",
"creationUser":"user1",
"updateUser":null,
"creationDate":1517495569000,
"updateDate":null,
"text":"Hello World"
},
{
"id":"543",
"creationUser":"user2",
"updateUser":"user3",
"creationDate":1517912985769,
"updateDate":1517921704448,
"text":"Hello people"
},
{
"id":"847",
"creationUser":"user 4",
"updateUser":null,
"creationDate":null,
"updateDate":1517913015110,
"text":"Text 1"
},
{
"id":"344",
"creationUser":"user 1",
"updateUser":"central",
"creationDate":1517912979283,
"updateDate":1517923926834,
"text":"Aloha!"
}];
data.sort(function (a,b) {
var aDate = a.updateDate?a.updateDate:a.creationDate;
var bDate = b.updateDate?b.updateDate:b.creationDate;
return aDate - bDate;
});
console.log(data)
((a.updateDate || 0) - (b.updateDate || 0)) || a.creationDate - b.creationDate
That compares by creation date if both updateDates arent set, otherwise the updateSet comes first.

Creating custom JSON object

I am having the below JSON object.
"Department": [
{
"depType": "Testing",
"name": "xyz",
"address":""
},
{
"deptype": "Developer",
"name": "abc"
}
]
I want to create another object based on the type of deptartment (depType). Something like this
"Testing":{
"name": "xyz",
"address":""
},
"Developer":{
"name": "abc"
}
With the help of Object.keys, I was able to get the keys
You had some Property-naming issues with camelCased "depType". Fix that.
Create a new copy of the desired object to manipulate using JSON.parse(JSON.stringify(orgObj))
Loop that object to find the desired Property "Department"
Since Department is an Array of Objects you need to loop that Array for(var i=0; i<dep.length; i++).
Than you'll need to match if that Array contains arrObj.hasOwnProperty( "depType" )
if successful you can than fill your new object with all the info newObj[arrObj.depType] = arrObj;
Since now, inside your new object there's also the good old "depType" property you can get rid of it using delete.
jsBin demo
var myjson = {
"Department": [
{
"depType": "Testing", // NOTE: "camelCase"
"name": "xyz",
"address":""
},
{
"depType": "Developer", // FIX: "camelCase" !!
"name": "abc"
}
]
};
function depTypify( orgObj ) {
var objCopy = JSON.parse(JSON.stringify(orgObj)); // Fresh copy
var newObj = {};
for(var prop in objCopy){
if(prop === "Department") {
var dep = objCopy[prop]; // get Department Array
for(var i=0; i<dep.length; i++) { // Loop array
var arrObj = dep[i]; // Explore Each Array Object
if(arrObj.hasOwnProperty( "depType" )) {
newObj[arrObj.depType] = arrObj;
delete arrObj.depType; // We don't need it any more
}
}
}
}
return newObj;
}
var myNewJson = depTypify( myjson );
if you do than console.log( myNewJson ) this is what you'll get:
[object Object] {
Developer: [object Object] {
name: "abc"
},
Testing: [object Object] {
address: "",
name: "xyz"
}
}
The nice thing is that your old json is still intact.

Functions indexed and declared in an Array, possibility and alternatives

I have some issues to organize my code.
Here is an example of what i would like to do:
var Test = {
old: [
get: function(who, when){
returrn({ subject: "Old test 001", text: "The test 001 was perform by "+who });
},
get: function(who, when){
returrn({ subject: "Old test 002", text: "The "+when+" the test 002 was performed"});
}
],
new: [
//Same thing
]
};
The thing is, we apparently can't do that, so i am wondering which is the way to declare functions in an Array ?
I need to do that because each method get() of the array can return a different message and the message can include the variables passed in parameters at different positions in the text, so i have to declare it explicitly.
I don't do like this:
var Test = {
old: [
one: {
get: function(who, when){
returrn({ subject: "Old test 001", text: "The test 001 was perform by "+who });
},
},
two: {
get: function(who, when){
returrn({ subject: "Old test 002", text: "The "+when+" the test 002 was performed"});
}
}
],
new: [
//Same thing
]
};
Because i need to access the content dynamically, like Test.old[test_id].get("toto", "02/04/2013"). and we unfortunatelly can't index things by numerical values in JSON.
However i'll do it like this is there is nothing better.
So what is the best thing to do in this context ?
Thanks !
The question is vague and confusing, but I can see why your code doesn't work. You're conflating arrays and objects. Array literals look like this:
var myArray = [
"first item",
"second item",
{value: "third item"},
["first/only item in fourth item"],
1,
2,
3.14159,
function(a,b) { return a + b; },
"etc."
];
Items in an array are accessed using push, pop, shift, unshift, and numerical indexes.
Object literal look like this:
var myObject = {
one: "some value",
two: {
value: "object values can be anything"
},
123: 456,
"a million": function (a, b) { return a - b; }
};
Items in an object are access using string indexes.
And finally, do you have a returrn() function declared somewhere? In either case, why not just return your return values?

Categories