Compare ObjectIDs for greater/smaller in JavaScript - javascript

I am aware you can query MongoDB for an object ID using the $gt and $lt operators. However, I would like to know how to compare two object IDs in this way but in plain JavaScript — not through a query.
I'm aware the ObjectID object has an equals method, but obviously that isn't what I need to test for greater/smaller than. I couldn't convert them to a timestamp and do the comparison that way because of the structure of ObjectIDs (with the incrementing counter at the end).

Convert the ObjectID objects to strings so that you can compare them:
if (oid1.toString() > oid2.toString()) { ... }
Or let JavaScript do the string conversions for you and just compare them directly:
if (oid1 > oid2) { ... }

Related

Prevent JSON.parse from rearanging an object

In my web application I receive a JSON string from the server which I keep in the greetings variable:
var greetings = '{"2":"hoi","3":"hi","1":"salam"}'
Please notice how the greetings start with the index 2 and the value hoi.
Now I want to parse the JSON and the result is the following:
JSON.parse(greetings) // {1: "salam", 2: "hoi", 3: "hi"}
The order has changed, it seems like JSON.parse orders the result by key.
Is there a way to keep the order of the original string intact?
{
"2":"hoi",
"3":"hi",
"1":"salam"
}
is not an array, its an object. Objects don't have any order.
If the order is important, you need to switch to an actual array.
You generally cannot rely on the order of indices in an object. Use an array of key/value pairs instead.
As you can see the keys are parsed to (numeric) indices, which is why they are ordered that way. You could hack around this by prefixing your keys and then stripping those later:
console.log(JSON.parse('{"i2":"hoi","i3":"hi","i1":"salam"}'))

Is it possible to store integer value in localStorage like in Javascript objects and extract it without typecasting?

When I assign integer value to localStorage item
localStorage.setItem('a',1)
and check its type
typeof(localStorage.a)
"string"
it returns string, I can typecast it to int for my use
parseInt(localStorage.a)
My question is it possible to store integer value inside localStorage as I can do for Javascript objects without typecasting?
a={};
a.number=1;
typeof(a.number)
"number"
My question is it possible to store integer value inside localStorage as I can do for Javascript objects without typecasting?
No.
Storage objects are simple key-value stores, similar to objects, but they stay intact through page loads. The keys can be strings or integers, but the values are always strings. [source]
Actually you can, if we agree that parsing is not the same as typecasting :
let val = 42;
localStorage.answer = JSON.stringify(val);
let saved = JSON.parse(localStorage.answer);
console.log( saved === val ); // true
Fiddle since over-protected stacksnippets don't allow localStorage.
For simplicity, you should anyway always stringify to JSON what you are saving in localStorage, this way you don't have to think about what you are saving / retrieving, and you will avoid "[object Object]" being saved.
You can store in numeric format using:
localStorage.setItem('object', JSON.stringify({
//Insert Number(value)
number: Number(1)
}));
// After get item
var object = localStorage.getItem('object');
console.log(JSON.parse(object));
Yes, you can store an integer in localStorage, but since it will be converted into a string, how do you actually know it was an integer? The question is not rhetorical. Storing an integer in localStorage is one thing (and easily accomplished), but knowing it's supposed to be an integer when you retrieve it is a different matter altogether. Not only do you have to keep track of the storage key value, you must also keep track of the data type.
What we really want is a mechanism that allows us to treat storage almost the same way we treat variables. If I am working with an integer, a float, a bigint, a string, a date, an array, a Boolean or an object then we would like to shove it into localStorage and get it back out. No conversion. No muss and no fuss.
This is precisely what localDataStorage does. (NOTE: I am the author.) The library transparently sets/gets key values using data "types" such as Array, BigInt, Boolean, Date, Float, Integer, Object and String. Store an integer, get it back. Working with dates, bigints or floats? No problem. And if you need to store arrays in localStorage, you can easily do so, as well as add and remove elements. Again, localDataStorage does all the heavy lifting for you. Let's have a look:
Include the library:
<script src="https://cdn.jsdelivr.net/gh/macmcmeans/localDataStorage#master/localDataStorage-2.0.1.min.js"></script>
Instantiate a namespaced copy:
const lds = localDataStorage( 'myapp-storage' );
Toss an integer in storage...
lds.set( 'myIntKey', 467 );
and get it back out:
let myInt = lds.get( 'myIntKey' );
console.log( myInt );
> 467
Ensure the data type was preserved:
typeof myInt;
> "number"
You can also check data types with the library:
lds.showtype( 'myIntKey' );
> "integer"
lds.isinteger( 'myIntKey' );
> true
lds.isnumber( 'myIntKey' );
> true
And of course we have some helper functions:
lds.haskey( 'myIntKey' );
> true
lds.hasval( 467 );
> true
lds.hastype( "integer" );
> true
The library also 1) provides lightweight data obfuscation; 2) intelligently compresses strings (to save storage space); 3) facilitates robust lookup including query by key (name), query by (key) value and query by existence (boolean check); 4) enforces segmented shared storage within the same domain by prefixing keys; and 5) responds to localStorage change events on the same page/tab that fired them. [/end glossyBrochure]

$.inArray is giving -1?

This should be pretty straight forward:
HTML
my link
<input type="hidden" id="pageids" value="28,27,26,17,18,19,">
Jquery
var thumbaid = $('#thumba').data("id");
// get position
var itemids = $('#pageids').val();
var itemids_array = itemids.split(',');
var currentpos = $.inArray(thumbaid, itemids_array );
alert(currentpos);
Gives me -1?
The funny thing is that if I replace " $(thumba).data("id")" for a number in the jquery code as "26", it works!
The result should be, in this case, "2".
Any ideas?
You need to convert the value to a string.
var thumbaid = $('#thumba').data("id").toString();
Why...? If you were to
console.log(itemids_array);
you would see this
["28", "27", "26", "17", "18", "19", ""]
They are not numbers, they are strings. See http://api.jquery.com/data/
That is because the thumbaid is a number, and the itemids_array contains strings. Try var currentpos = $.inArray(thumbaid.toString(), itemids_array );
jQuery's data function reads the data- attributes and parses digits to numbers.
jQuery's data function does things to the data it reads from the data-* attributes on initialization, including turning number-like strings into numbers. Since $.inArray does an === check, that's why it fails. You end up looking for the number 26 in an array of strings.
If you simply use .attr("data-id") instead, the conversion won't happen.
This behavior is documented in the data docs:
Every attempt is made to convert the string to a JavaScript value (this includes booleans, numbers, objects, arrays, and null). A value is only converted to a number if doing so doesn't change the value's representation. For example, "1E02" and "100.000" are equivalent as numbers (numeric value 100) but converting them would alter their representation so they are left as strings. The string value "100" is converted to the number 100.
If you're only using data to read data-* attributes, I recommend using attr instead to avoid this kind of thing, and to avoid the confusion caused by the fact that while data initializes from data-* attributes, it doesn't write to them when you set data. Of course, if you need to store data associated with elements and you don't want it on an attribute (because it's not string data, or you don't want it showing in the DOM inspector), data is the right tool for that job.
The reason its not working, is because jQuery data is returning an int not string.
See this example.
my link
<input type="hidden" id="pageids" value="28,27,26,17,18,19,">
Javascript:
var thumbaid = $('#thumba').data('id').toString();
// get position
var itemids = $('#pageids').val();
var itemids_array = itemids.split(',');
console.log(itemids_array);
var currentpos = $.inArray(thumbaid, itemids_array );
console.log(currentpos);
$().data() will convert the data-* attribute's value to a JavaScript value. In your case, thumbaid is converted to a number.
$.inArray compares elements using the strict equality operator(===). That is, '26' === 26 returns false as no type coercion occurs.
From the jQuery.data() docs:
Every attempt is made to convert the string to a JavaScript value
(this includes booleans, numbers, objects, arrays, and null). A value
is only converted to a number if doing so doesn't change the value's
representation. For example, "1E02" and "100.000" are equivalent as
numbers (numeric value 100) but converting them would alter their
representation so they are left as strings. The string value "100" is
converted to the number 100.

flatten/expand objects: am I on the right tracks?

I want to flatten a multi-level object and vice versa.
For example:
{
option1:value1,
option2:value2,
option3:{
key1:value31,
key2:value32
},
option4:[value40,value41,value42]
}
Would be equivalent to:
{
option1:value1,
option2:value2,
"option3.key1":value31,
"option3.key2":value32,
"option4.0":value40,
"option4.1":value41,
"option4.2":value42
}
This is for small objects, the objective of the flattened expression is to facilitate the data collection in a form and the merge with default options. For example I can have form elements like this:
<input name="option4.0" value="value40"/>
Is this a standard approach, or is there a better way? Are there libraries that already do this?
That format ({ option4.2: value42 }) won't work (because the . in the key will be parsed as a dot operator). Instead, you'll need to quote the key:
{ 'option4.2': value42 }
However, this is very non-standard. Flattening objects is typically not required - if you want to submit such an object to a server, you can use JSON to serialize it without flattening:
var stringForServer = JSON.stringify(normalObject);
If you're looking for a library to manipulate objects and arrays etc, underscore is probably your best bet:
http://underscorejs.org/
cheers!
I experimented with my idea, it works fine but has a few limitations.
The obvious ones is that a key cannot contain a dot (dots are delimiters with this technique), and keys cannot be numbers (or else the algorithm interprets it as an array index).
Another issue is that it won't work if a value is an empty object or array (e.g. option4:[]).

Converting an array to a string in Javascript

I have a multi-dimensional array like this:
1 2 3
4 5 6
Now I need to convert this array into a string like 1,2,3;4,5,6.
Can any one suggest how to do this, please?
simply use the join method on the array.
> [[1,2,3],[4,5,6]].join(';')
'1,2,3;4,5,6'
It's lucky that you simply don't have to consider how the apply the join method on the inner lists, because a list is joined by comma by default. when a list is coerced into a string, it by default uses commas to separate the items.
As it was already mentioned by qiao, join() is not recursive.
But if you handle the recursion yourself you should acquire the desired result, although in a rather inelegant way.
var array = [[1,2,3],[5,6,7]];
var result = [];
array.forEach(
function(el){
result.push(
el.join(",")
);
});
result.join(";");
If you need to serialize an array into a string and then deserialize it later to get an array from the string you might want to take a look at JSON:
http://www.openjs.com/scripts/data/json_encode.php
Try this:
array.toString();
See here for reference: http://www.w3schools.com/jsref/jsref_tostring_array.asp
See answer by qiao for a much nicer approach to multidimensional arrays like this.

Categories