Javascript Filtering JSON data - javascript

Sample JSON data:
{
"assignments": [{
"date": "2022-04-01",
"lName": "lastname",
"uId": "12345",
"uCode": "LName1",
"fName": "FName1 ",
"aName": "AsignmentName1",
"aId": "998"
}]
}
I'd like to filter the following data to get a specific element's contents based on searching for an assignment name.
For instance in SQL like terms
Select * FROM assignments WHERE `aName` = 'AssignmentName1'
I'm sure this is simple but having trouble with methods for how to accomplish it.
Thanks

I am new here, but if you have access to modern day JavaScript, I would do something like:
const data = JSON.parse('{"assignments":[{"date":"2022-04-01","lName":"lastname","uId":"12345","uCode":"LName1","fName":"FName1 ","aName":"AsignmentName1","aId":"998"}]}';
const yourMatch = data.assignments.find(c => c.aName === 'AssignmentName1');
Since data.assignments is an array, you can call the find() function on it. This functions takes a 'search'-function/lambda as argument.
This search function basically takes an element and decides, whether it is the one you search for, or not aka it returns a boolean.
In my example the arrow function is c => c.aName === 'AssignmentName1', which is shorter and easier to read than a normal function definition. (You can call c whatever you want, it's just cleaner this way.)
You can exchange find() with filter(), if you accept multiple results and not just the first one.

You first have to parse the JSON string:
const parsedJSON = JSON.parse(jsonString);
The object returned is contains all the data from your JSON string. To access the assignments array you can use dot notation.
const assignments = parsedJSON.assignments;
If you don't need to support old browsers, ES6 has a handy function for finding the value in an object. Use the "find"-function and pass a function that returns true for the item you are looking for:
const selectedAssignment = assignments.find( (assignment)=> {
return assignment.aName=="AssignmentName2";
});
If you don't want to use ES6 you can use a for loop.
var assignments = JSON.parse(jsonString).assignments;
function getAssignmentWithName(name) {
for (var i = 0; i < assignments.length; i++) {
if (assignments[i].aName == name) {
return assignments[i];
}
}
return false;
}
var selectedAssignment = getAssignmentWithName("AssignmentName1");

Related

Compare object property to variable in localstorage in JavaScript

Is it possible to compare an object property to a variable stored in localstorage using Javascript or Jquery? Here's what I mean...
So I have an object like this:
var persons = [
{
"firstName": "Dwight",
"surName": "Stender",
"picture": "https://randomuser.me/api/portraits/med/men/99.jpg",
"id": "1"
}
]
And I have a variable stored in localstorage (the name is clickId). Now I want to compare the id from the object to that variable in localstorge. I can print them both to the console so I know they work. But when I try to compare them, it suddenly doesn't work anymore (even though the id and the variable contain the same number). This is how I compared the two:
for (i = 0; i < persons.length; i++) {
if (persons[i].id == localStorage.clickId) {
document.getElementById("result").innerHTML = "yay"
} else {
document.getElementById("result").innerHTML = "nay"
};
};
Note 1 I have also tried comparing the two with === instead of ==
Note 2 the statements to be executed inside the if...else are just placeholders for the purpose of explanation
You need to use localStorage.getItem(key) to retrieve the object you previously stored. Also note that as localStorage can only hold string you'd need to serialise the object before/after saving it. JSON would be ideal for this:
Also note that you can use some() to negate the for loop, and a ternary to simplify the if.
var persons = [{
"firstName": "Dwight",
"surName": "Stender",
"picture": "https://randomuser.me/api/portraits/med/men/99.jpg",
"id": "1"
}];
var person = JSON.parse(localStorage.getItem('person') || '{}');
document.getElementById("result").innerHTML = persons.some(p => p.id == person.clickId) ? "yay" : 'nay';
localStorage.setItem('person', JSON.stringify({
clickId: 1
}));
<div id="result"></div>
Working example
you can use the inArray method of Jquery without need to use the loop
$.inArray(value, array)
Returns index of value in array. Returns - 1 if the array does not contain the value

Cleaner way to update object in array

I have an array of objects formatted like this:
{
"_id": "590cbcd9bf2b9b18ab3c3112",
"title": "",
"content": "Create Notes Webapp",
"checked": true,
"listID": "590cbc61bf2b9b18ab3c3110"
},
{
"_id": "590cfe5a86fe0908c560c2b0",
"title": "A Note 01",
"content": "My first note.",
"checked": false,
"listID": "590cbe15bf2b9b18ab3c3114"
}
Here is the code I have to update each item:
onTextChange = (key, note, value) => {
clearTimeout(timeoutID);
switch (key) {
default:
break;
case 'title':
note.title = value;
break;
case 'checked':
note.checked = value;
break;
case 'content':
note.content = value;
break;
}
var notes = this.state.notes;
var id;
for (var i in notes) {
if (notes[i]._id === note._id) {
notes[i] = note;
id = i;
break;
}
}
this.setState({ notes }, () => { timeoutID = setTimeout(() => this.updateNote(this.state.notes[id]), 3000); });
}
This is called like this:
onChange={(e, value) => this.onTextChange('title', note, value)}
Is there a better way than using that switch statement to update the specified item in the object? Also, is there a simpler method of scanning the array for the id than the for loop?
Is there a better way than using that switch statement to update the specified item in the object?
You can use this syntax to update the note object. This also makes sure it does not insert new properties into note.
if (note.hasOwnProperty(key) {
note[key] = value
}
For a cleaner syntax to update notes you could do
var newNotes = this.state.notes.map(n => n._id === note._id ? note : n);
this.setState({notes: newNotes});
This will create a newNotes array which is identical to the current state except it will replace the one where the passed in ._id is equal to the one in the array.
You would also have to adjust the updateNote call because you no longer save the index but you could probably just use the note variable?
instead of switch you can do this but you have to check if it exists in the object.
onTextChange = (key, note, value) => {
clearTimeout(timeoutID);
if(note[key]){
note[key] = value;
}
var notes = this.state.notes;
var id;
}
As for looping it is preferred by most standard like airbnb and google.
if you want a better way you can do several things with that array of objects depending on the situation and if you're using es5, es6, but your options are:
1. Make array of objects into an object with key (property name) be your id (they can be any strings).
2. if es6 is used you can convert into map and it makes it so much lighter and faster to get needed object.
hope that helps.
Just as noveyak said, you can access properties in Javascript by using the bracket syntax, where the key is a string containing the name of the property (as you have it now).
Javascript has several different ways of accessing object properties:
note[key] = value;
// if key is 'title', it will be the same as:
note.title = value;
// also the same as:
note['title'] = value;
For your second question, instead of looping over an array, you can store those objects in another object with the id as the property value (essentially using it as a map). This way you can directly access the note entries by id. For example:
allNotes = {}; // create a new object
someNotes = {
'title': '',
'content': 'Create Notes Webapp',
'checked': true,
'listID': '590cbc61bf2b9b18ab3c3110'
};
allNotes[idOfNote] = someNote; // where idOfNote holds the actual id of the note as a string
You can read more about Javascript property accessors on Mozilla's reference website here.
Javascript also has proper maps you can use instead of an object, which is safer and faster if you're allowed to use ES2015. You can learn about it here (also Mozilla docs).

lambda like matching on json object for javascript backbone?

not a front end SME....is there a javascript or backbone(_) equivalent of this java 8 lambda instead of looping over a JSON array and matching on "type"? :
{
"things": [
{
"type": "THE_OTHER_THING"
},
{
"type": "MY_THING"
}
]
}
.
thing theThing = things.stream().filter(x -> x.getType() == ThingType.MY_THING).findFirst().orElse(null);
Assuming you are looking to iterate through an array and only return objects with a given type, I would suggest the following:
For single or little use, you could simply create the function that asserts the type of your choice:
function isThing(jsonObject) {
return jsonObject.type === "THIS_THING";
}
Or to avoid hard coding:
var THING_TYPE = "THIS_THING";
function isThing(jsonObject) {
return jsonObject.type === THING_TYPE;
}
Then you can apply this function to an array using its filter method.
var filteredList = completeList.filter(isThing);
filter, as described on MDN Array.prototype.filter, takes a function as an argument and applies it to every element within the array. If the function returns true, the element is added to a new array. Once the passed function has been applied to each element, the filter function returns the new array.
The above choice may be practical if you are simply looking for one or two types. However, if you have many types for which you might want filters, you should consider abstracting this away slightly, like so:
function createFilterWithType(desiredType) {
// will return true if jsonObject is of desired type
var typeAsserter = function (jsonObject) {
return jsonObject.type === desiredType;
}
return typeAsserter;
}
// Create functions that assert if object is given type
var isThisThingType = createFilterWithType("THIS_THING");
var isOtherThingType = createFilterWithType("OTHER_THING");
// Data
var completeList = [
{type:"THIS_THING", id:0},
{type:"OTHER_THING", id:1}
];
// Data filtered by applying asserters to completeList
var thingTypeList = completeList.filter(isThisThingType);
// returns [{type:"THIS_THING", id:0}]
var otherTypeList = completeList.filter(isOtherThingType);
// returns [{type:"OTHER_THING", id:1}]
Alternatively, you can create the asserters and apply in a single step:
var thingTypeList = completeList.filter(createFilterWithType("THIS_THING"));
var otherTypeList = completeList.filter(createFilterWithType("OTHER_THING"));
Though you remove a few lines by doing so, you lose in performance as each invocation of filter requires the creation of the anonymous assertion function. Worse still, compacting your code this way can make it far more difficult to reason about.

JSON.stringify() only allows one value parameter. How do I add more parameters to be stringified under one brace?

http.get(options, function(res){
fs.appendFile('log.txt', JSON.stringify(res.headers, null, 4));
})
I have a question regarding the JSON.stringify() function.
I've learned that simply using the res.headers does not in fact output to JSON format.
At the moment, I am restricted to only being able to use one res.xxxxx method within JSON.stringify(). The piece of code in question is pasted above. How am I able to use more than one value? At the moment, I can only put in res.headers into the value parameter. I would also like to use res.statusCode and my own objects, all stringified under one brace {}.
The parameters of JSON.Stringify is as follows: JSON.stringify(value, [replacer], [space]);
You need to create a new js object and put res.headers into it.
var obj = {};
obj.headers = res.headers;
obj.somethingelse = somethingelse;
var string = JSON.stringify(obj);
JSON is always a single value. So the output out JSON.stringify can always only be a single value. It would make sense to have the input be a single value too. This is like asking why can't my function return two things? You can make it return some composite value, but that means you're still returning a single (composite) value. The solution here is the same, compose your input.
var reply = {
code: res.statusCode,
headers: parse_http_headers(res.headers),
etc: /* etc */
};
log(JSON.stringify(reply));
Note that you must write parse_http_headers yourself.
You could always add the extra things you want to the headers object...
res.headers.statusCode = res.statusCode
JSON.stringify(res.headers, null, 4);
I don't know if there are any bad side effects if you mutate the res object in node. You might want to consider creating a shallow copy of the headers object if you are worried about that.
You could as well stringify more than only the headers part of your object:
JSON.stringify(res, …)
If you want to stringify only certain parts of your object, you can
filter them with the replacer function,
delete everything else before,
or build a new object to be stringified:
JSON.stringify({
heads: res.headers,
…
}, …)
If you'd like to flatten several objects, you can use this function.
function merge() {
var out = {};
insert = function(e) {
for (var i in e) {
if (Object.prototype.hasOwnProperty.call(e, i))
out[i] = e[i];
}
};
for (var i = 0; i < arguments.length; i++) {
insert(arguments[i]);
}
return out;
}
var a = {'a': 'aa'};
var b = {'b': 'bb', 'bbb': 'bbbb'};
var c = {'c': 'cc'};
var combined = merge(a,b,c);

How to implement such an associative array?

arr[key] = value;
where key is a jQuery object and value is an array.
Associative arrays don't really exist in JavaScript. However, you can achieve similar functionality using JavaScript objects:
// Create object
var myObject = {
key: value,
helloText: "Hello World!"
};
// Access object in some statement via:
myObject.helloText
// ...or:
myObject["helloText"]
To use an object as a key, you would have to do something like:
var a = {
helloText: "Hello World!"
};
var b = {};
b[a] = "Testing";
alert(b[a]); // Returns "Testing" (at least, in Safari 4.0.4)
Using an object as a key sounds a bit weird, though. Are you sure you need to do this?
Update:
You can't actually use an object as a key in JavaScript. The reason the above code appears to work is that, in the statement b[a] = "Testing";, JavaScript converts a to a string via a.toString(), which results in "[object Object]", and uses this string as the key. So our statement is actually b["[object Object]"] = "Testing"; and our alert statement is exactly the same as alert(b["[object Object]"]);.
Thanks to CMS for pointing this out in the comments!
Update 2:
Tim Down points out that his JavaScript library jshashtable allows you use an object as a key.
You can use jshashtable, which allows any JavaScript object as a key.
Just guessing here, but it seems you're trying to associate some (arbitrary) data with a jQuery object (possibly an element). In that case, why not use the data () method?
$('#el').data (value);
You can't use objects as keys, and assocative arrays are not what they seem in Javascript because all you're doing is setting a property on the array object, when you loop through by the .length it natively doesn't account for the manually defined properties you set.
I suggest storing the elements and arrays inside of object literals, all inside of an array. Eg:
var list = [
{
el:document.body,
arr:[1,2]
}
];
for ( var i = 0, l = list.length; i<l; ++i ) {
alert( list[i]['el'] )
alert( list[i]['arr'][0] )
}
// add elements to the array
list.push({
el:document.body.firstChild,
arr:[3,4]
})
As kprime mentioned in his answer though, it might be better to use .data() if you are using Javascript.
if ( !$(el).data('key') ) {
$(el).data('key', [2,3,4] );
}
I would suggest assigning a unique ID to each element you want to put in the associative container (object in JS) and use the ID as key:
var idCounter = 0;
var container = { };
function storeValue(element, value) {
if (!element.getAttribute('id')) {
element.setAttribute('id', makeID());
}
var id = element.getAttribute('id');
container[id] = value;
}
function makeID() {
return 'unique-id-' + idCounter++;
}
EDIT: This solution assumes that jQuery is not available. If it is, use data('key', value).
every javascript object is an associative array, this is a property build in the language, you do not need to anything special, just use it like that

Categories

Resources