Why does this array have object key value pairs? - javascript

I didn't even know that this was possible, what is this? I tried running this on chrome and firefox, and got the same result:
I'm sending a 100 item array from the server, but when it gets to the client, this happens.
I tried accessing the item at index 100, and got undefined as response.
I also tried slicing it to the first 100 items, but the rest of the key pairs remain there.
I can't try to access the values by key because they are random every time. If that's of any value.

Since an array is also an object, you can add arbitrary properties to it. Run this code then look in your browser console (not the console inside this post).
const array = ['11034.61000000', '0.30200000'];
array['10987'] = 0.009101;
array['11024.05'] = 0.001998;
array['11026.96'] = 0.001;
array['11026.59'] = 1.5;
console.log(array);
console.log(Object.keys(array));
Object.keys(array) will show you every property of the array, even the random ones.

Related

IndexOf not working properly

I am completing a fairly complicated process in node and for it to work properly I need to compare the value of a key in an object to an array. I have checked to make sure I have no async issues and am simply using a indexOf to get the index of the object's key in the array. I have checked the typeof each item and both return "object" "object". Here is an example check that I am making.
var cID = [55cebe83d0b3d];
var item = { _id: 55cebe83d0b377d,
_client: 55cebe83d0b3d,
institution_type: 'test' }
var cIndex = cID.indexOf(item._client)
and then cIndex always equals -1 regardless of it really exists within cID. If I console log item._client it is 55cebe83d0b3d which is exactly what is stored within cID but still returns -1. Any ideas? I also have the data coming from MongoDB and the data is going through body-parser before hitting this function.
I suppose that hex numbers are not js-native. Turn them into hex strings. E.g. '5cebe83d0b377d' instead of 5cebe83d0b377d.
Update
Mea culpa, see Hiyper's comment.

why are my javascript floating point numbers getting sliced up?

I have an array filled with latitude and longitude pairs pushed like this
doneDotsA.push(lat+"|"+lon);
the values can look like 51.5 or -0.11666666666666667, etc.
then the array is stored in a cookie as an array.
when I try to read the cookie contents it looks like this when In examine it
alert('doneDotsA='+doneDotsA.toString());
yields results like this:
doneDotsA=51.5|-0.11666666666666667
so far so good. however when I try to extract the values like this
for (var t = 0; t < doneDotsA.length; t++) {
alert('val='+doneDotsA[t]);
}
the alert shows 'val=5' then 'val=1' then 'val=.' then 'val=5' etc. somehow reading only one character at a time instead of returning the full number as I'd expect it to do.
does saving an array into a cookie do something to the numbers?
any ideas?
stored in a cookie as an array
Cookies are always stored and retrieved as a string, unless you use custom code to rebuild it into an array after the fact.
A solution like this could be to take your latitude and longitude and put them into a JSON object for serialization and storage in the cookie. Then you can parse them into objects when the site loads.
var coords = {
points:[
{lat:12.4444446,lon:44.55555},
{lat:12.4444446,lon:44.55555}
]
};
var serialized = JSON.stringify(coords);
toStore(serialized);
Then you can just set it to local store or to anyplace you can store a string.
var myLoaded = fromStore();
var coords = JSON.parse(myLoaded);
coords.points.each(function(coord) {
// do something with points.
});
You should then be able to do something with the points you saved.
One note: you might want to check that myLoaded is not an empty string or wrap parse in a try/catch block. A poorly formed structure will throw an exception.

Is there a way to map a value in an object to the index of an array in javascript?

Prepending that a solution only needs to work in the latest versions of Chrome, Firefox, and Safari as a bonus.
-
I am trying to use an associative array for a large data set with knockout. My first try made it a true associative array:
[1: {Object}, 3: {Object},...,n:{Object}]
but knockout was not happy with looping over that. So I tried a cheating way, hoping that:
[undefined, {Object}, undefined, {Object},...,{Object}]
where the location in the array is the PK ID from the database table. This array is about 3.2k items large, and would be iterated over around every 10 seconds, hence the need for speed. I tried doing this with a splice, e.g.
$.each(data, function (index, item) {
self.myArray.splice(item.PKID, 0, new Object(item));
}
but splice does not create indices, so since my first PKID is 1, it is still inserted at myArray[0] regardless. If my first PK was 500, it would start at 0 still.
My second thought is to initialize the array with var myArray = new Array(maxSize) but that seems heavy handed. I would love to be able to use some sort of map function to do this, but I'm not really sure how to make the key value translate into an index value in javascript.
My third thought was to keep two arrays, one for easy look up and the other to store the actual values. So it combines the first two solutions, almost, by finding the index of the object in the first example and doing a lookup with that in the second example. This seems to be how many people manage associative arrays in knockout, but with the array size and the fact that it's a live updating app with a growing data set seems memory intensive and not easily manageable when new information is added.
Also, maybe I'm hitting the mark wrong here? We're putting these into the DOM via knockout and managing with a library called isotope, and as I mentioned it updates about every 10 seconds. That's why I need the fast look up but knockout doesn't want to play with my hash table attempts.
--
clarity edits:
so on initial load the whole array is loaded up (which is where the new Array(maxLength) would go, then every 10 seconds anything that has changed is loaded back. That is the information I'm trying to quickly update.
--
knockout code:
<!-- ko foreach: {data: myArray(), afterRender: setInitialTileColor } -->
<div class="tile" data-bind="attr: {id: 'tileID' + $data.PKID()}">
<div class="content">
</div>
</div>
<!-- /ko -->
Then on updates the hope is:
$.each(data.Updated, function (index, item) {
var obj = myModel.myArray()[item.PKID];
//do updates here - need to check what kind of change, how long it's been since a change, etc
}
Here is a solution how to populate array items with correct indexes, so it doesn't start from the first one (0 (zero) I meant)
just use in loop
arr[obj.PKID] = obj;
and if your framework is smart (to use forEach but not for) it will start from your index (like 500 in case below)
http://jsfiddle.net/0axo9Lgp/
var data = [], new_data = [];
// Generate sample array of objects with index field
for (var i = 500; i < 3700; i++) {
data.push({
PKID: i,
value: '1'
});
}
data.forEach(function(item) {
new_data[item.PKID] = item;
});
console.log(new_data);
console.log(new_data.length); // 3700 but real length is 3200 other items are undefined
It's not an easy problem to solve. I'm assuming you've tried (or can't try) the obvious stuff like reducing the number of items per page and possibly using a different framework like React or Mithril.
There are a couple of basic optimizations I can suggest.
Don't use the framework's each. It's either slower than or same as the native Array method forEach, either way it's slower than a basic for loop.
Don't loop over the array over and over again looking for every item whose data has been updated. When you send your response of data updates, send along an array of the PKIds of the updated item. Then, do a single loop:
.
var indexes = []
var updated = JSON.parse(response).updated; // example array of updated pkids.
for(var i=0;i<allElements.length;i++){
if(updated.indexOf(allElements[i].pkid)>-1)
indexes.push(i);
}
So, basically the above assumes you have a simple array of objects, where each object has a property called pkid that stores its ID. When you get a response, you loop over this array once, storing the indexes of all items that match a pk-id in the array of updated pk-ids.
Then you only have to loop over the indexes array and use its elements as indexes on the allElements array to apply the direct updates.
If your indexes are integers in a reasonable range, you can just use an array. It does not have to be completely populated, you can use the if binding to filter out unused entries.
Applying updates is just a matter of indexing the array.
http://jsfiddle.net/0axo9Lgp/2/
You may want to consider using the publish-subscribe pattern. Have each item subscribe to its unique ID. When an item needs updating it will get the event and update itself. This library may be helpful for this. It doesn't depend upon browser events, just arrays so it should be fairly fast.

How do I use #DbLookup results to populate a Readers field in xpages?

db = new Array("myserver", "myfolder\\mydb.nsf")
dir = getComponent("Dir").value;
div = getComponent("Div").value;
lu = #DbLookup(db, "ManagerAccess", dir + "PP" + div, "DTManagers");
var a = [];
a.push(lu);
var item:NotesItem = docBackEnd.replaceItemValue('FormReaders', #Unique(a));
item.setReaders(true);
That code is on the querySaveDocument ssjs. The result I get from the #DbLookup (when I put in a computed field) look like this:
Pedro Martinez,Manny Ramirez,David Ortiz,Terry Francona
I tried doing an #Explode(#Implode) thing on it, but it doesn't seem to work.
The error I get in the browser just tells me that the replaceItemValue line is broken.
To test it, I pushed several strings one at a time, and it worked correctly populating my FormReaders field with the multiple entries.
What am I doing wrong?
I see several problems here:
A. In cases as described by you #Dblookup in fact would return an array. If you push an array into a plain computedField control it will exactly look as that you wrote:
value1, value2, ..., valueN
A computedField doesn't know anything about multiple values etc, it just can display strings, or data that can be converted to strings.
If you want to test the return value you could try to return something like lu[0]; you then should receive the array's 1st element, or a runtime error, if lu is NOT an array. Or you could ask for the array's size using lu.length. That returns the number of array elements, or the number of characters if it's just a plain string.
B. your code contains these two lines:
var a = [];
a.push(lu);
By that you create an empty array, then push lu[] to the first element of a[]. The result is something like this:
a[0] = [value1, value2, ..., valueN],
i.e. a is an array where the first element contains another array. Since you don't want that, just use #Unique(lu) in your replaceItemValue-method.
C. I don't see why replaceItemValue would throw an error here, apart from what I wrote in topic B. Give it a try by writing lu directly to the item (first without #Unique). That should work.
D. for completeness: in the first line you used "new Array". A much better way to define your db parameters is
var db = ["myserver", "myfolder/mydb.nsf"];
(see Tim Tripcony's comment in your recent question, or see his blog entry at http://www.timtripcony.com/blog.nsf/d6plinks/TTRY-9AN5ZK)

Changing the variables of a class in OOP in javascript

I have defined a function called Node which stores the properties of nodes in a graph data structure. The function is something like this:
function Node(){
...
this.outEdges = [];
this.inEdges = [];
...
}
where the inEdges and outEdges store elements of type Edge which is another function I have defined. During the program these arrays are filled with elements.
At some point in my code I need to reset these two arrays so I write:
nodes[i].outEdges.length = 0;
nodes[i].inEdges.length = 0;
where nodes is an array of elements of type Node and I am accessing an element in a for loop.
The problem is, after setting outEdges and inEdges to 0, I expected them to be [] in the nodes[i] property list. However, when I output nodes[i] into console, the outEdges and inEdges still have the elements in them. The stranger thing is that when I output nodes[i].outEdges to console, it prints [] , which is correct, but clicking on [ ] again opens the list of the elements! I can't really figure out why the nodes[i] variables don't change?
That happens (probably) because the browser prints out the empty array but by the time you check it, it has content again. So when you click to expand the browser shows the actual content.
As you can see the values [1,3,7] were added after the command console.log(o) but they are shown on the screen (even though the length shown is 0).
You're not supposed to set the length field. Just re-initialize them:
nodes[i].outEdges = [];
nodes[i].inEdges = [];
Edit: My bad, setting the length should work. It does work for me on Chrome at least. However, I still think it's safer and better style to re-init.
Just create a new object with the same name
nodes[i].outEdges = new Array();

Categories