How to create random key in React? - javascript

Each element in list must have a unic key. So how can create this key?
I did function which return keys like this:
QV8938
XN0210
DC7389
DC8376
HA8357
etc. With random. Is it normal to create such keys?

Is it normal to create such keys?
No, and it's not a good idea. Read the Lists and Keys documentation.
There are three separate problems with random keys:
If they're random, you might end up with the same key on more than one item. (You can mitigate this problem with a sufficiently-powerful random generator like ones used for GUIDs, though.)
You'll cause unnecessary work committing to the DOM for something that hasn't actually changed when its key changes.
You'll cause display errors by not re-committing to the DOM when something does change but its key doesn't change.
Instead, derive your keys from the data for the items being displayed, which is always possible, even if it means you have to create artificial keys for them and then reuse those artificial keys.
You might be tempted to use array indexes as keys. That's not a good idea either in almost any case (that post is linked from the documentation above). The only exception is a static array of static items — nothing in it is ever modified, nor does its order ever change; in that one case, using the index as a key is okay.

Related

Fastest way to check for an object's existence in a list in JavaScript

I've got a list of 100,000 items that live in memory (all of them big ints stored as strings).
The data structure these come in doesn't really matter. Right now they live in an array like so:
const list = ['1','2','3'...'100000'];
Note: The above is just an example - in reality, each entry is an 18 digit string.
I need to check for an object's existence. Currently I'm doing:
const needToCheck = '3';
const doesInclude = list.includes(needToCheck);
However there's a lot of ways I could do this existence check. I need this to be as performant as possible.
A few other avenues I could follow are:
Create a Map with the value being undefined
Create an object ({}) and create the keys of the object as the entries in list, then use hasOwnProperty.
Use a Set()
Use some other sort of data structure (a tree?) due to the fact that these are all numbers. However, due to the fact that these are all 18 digits in length, so maybe that'll be less performant.
I can accept a higher upfront cost to build the data structure to get a bigger speed increase later, as this is for a URL route that will be hit >1MM times a day.
Array.prototype.includes is an O(n) operation, which is not desirable - every time you want to check whether a value exists, you'll have to iterate over much of the collection (perhaps the entire collection).
A Map, Set, or object are better, since checking whether they have a value is an O(1) operation.
A tree is not desirable either, because lookup will necessarily take a number of operations down the tree, which could be an issue if the tree is large and you want to lookup frequently - so the O(1) solution is better.
A Map, while it works, probably isn't appropriate because you just want to see if a value exists - you don't need key-value pairs, just values. A Set is composed of only values (and Set.has is indeed O(1)), so that's the best choice for this situation. An object with keys, while it could work too, might not be a good idea because it may create many unnecessary hidden classes - a Set is more designed towards dynamic values at runtime.
So, the Set approach looks to be the most performant and appropriate choice.
You might also consider the possibility of moving the calculation to the server. 100,000 items isn't necessarily too much, but it's still a surprisingly large amount to see client-side.
Unconventionally, you could also use an object and set each of your 100,000 items as a property because under the hood, the JavaScript Object is implemented with a hash table.
For example,
var numbers = {
"1": 1243213,
"2": 4314121,
"3": 3142123
...
}
You could then very quickly check if an item existed by checking if numbers["1"] === undefined. And not only that, but you can also get the value of of the property at the same time.
However, this method does come with some drawbacks like iterating through the list becoming a lot more complicated (though still possible).
For reference, see https://stackoverflow.com/a/24196259/8250558

javascript (ES6): Why do we need sets?

My question is why do we need sets in ES6 and what is their actual difference from an array of strings? Can you define an example where a set is more accurate than an array of strings? I get it that maps save you the trouble of messing with objects, but sets just seem to serve no purpose.
The purpose of a Set is to enforce uniqueness. If the value you try to put in there already exists, then you will still just have one entry, not two like you would when pushing to an array. Additionally, trying to check if a set contains a certain element is a quick operation (constant time, aka O(1)), while trying to do the same with an array is slower (linear time, aka O(N)).

Javascript Implementation of Python Dictionary

So, I just learnt about python's implementation of a hash-table, which is dictionary.
So here are what I understand so far, please correct me if I'm wrong:
A dictionary is basically a structured data that contains key-value pairs.
When we want to search for a key, we can directly call dict[key]. This is possible because python does a certain hash function on the key. The hash results is the index of the value in the dictionary. This way, we can get to the value directly after doing the hash function, instead of iterating through a list.
Python will update the hash-table by increasing the amount of 'buckets' when the hash-table is filled 2/3rd of its maximum size.
Python will always ensure that every 'buckets' will only have 1 entry in it so that the performance on lookup will be optimal, no iterations needed.
My first question is, am I understanding python dictionary correctly?
Second, does the javascript object also has all these 4 features? If not, is there another built-in javascript implementantion of dictionary/hash-table in general?
JavaScript Objects can be used as dictionaries, but see Map for details on a JavaScript Map implementation. Some key takeaways are:
The Object prototype can potentially cause key collisions
Object keys can be Strings or Symbols. Map keys can be any value.
There is no direct means of determining how many "map" entries an Object has, whereas Map.prototype.size tells you exactly how many entries it has.
As a rule of thumb: if you're creating what is semantically a collection (an associative array), use a Map. If you've got different types of values to store, use an Object.

What reasons are there for using Arrays instead of Objects to store lists other than helper functions?

TL:DR
Beside the use of the convent Array helper functions (which I could theoretically create for objects), and considering the performance advantage of Object lookups, what reason could be given to use an Array instead of an Object?
Objects
From what I understand, because JavaScript objects use hash tables to lookup their key -> data pairs, the look-up time, no matter the length of the object is very small.
For example if I want a really fast dictionary look up, in the past I've (and we can condense the syntax but that's besides the point) stored dictionary data in JSON as
"apple" : "apple",
and then used
if (Dictionary.apple) console.log("Yep it's a word!");
And the result return very very fast regardless of whether my dictionary contains 30,000 words or 300,000.
Arrays
On the other hand, unless I know the number an array item is attached to, I have to loop through the entire array, causing larger lookup times the further the item is down the list.
The good thing I know of about using an array is that I get access to convenient functions such as slice, but these could probably be created for use with objects.
My Question
So, considering the lookup efficiency of objects, I'd currently choose an object over an array for every situation. But I could easily be wrong about this.
Beside the use of the convent Array helper functions (which I could theoretically create for objects), and considering the performance advantage of Object lookups, what reason could be given to use an Array instead of an Object?
You're comparing apples to oranges here. If you need to map from arbitrary string keys to values, as in your example with "apple", then you use an object. (In ES2015, you might alternatively use a Map instance.)
If you have a whole bunch of oranges, and you want to keep them in a list numbered from 0, you put the oranges in an array and index by which (numbered) orange you want.
The process of locating a property on an object is the same whether the object is a plain Object instance or an Array instance. In modern JavaScript runtime environments, it's safe to assume that the process for looking up number-indexed array properties is appropriately optimized to be even faster than the hash lookup for arbitrary string-named properties. That, however, is a completely separate issue from the nature of the work you need to do and the choice of data structure. Either you have a list of things, such that the order of the things in the list is the salient relationship between them, or you have named things that you need to access by those names. The two situations are conceptually different.
One big difference is the order of elements.
Looping through objects keys can't guarantee any specific order.
Looping through array keys will always give you the same order of elements.

Adobe DTM and arrays with varying numbers of elements

On our site, we have pages that can be assigned tags, and I'm having issues with figuring out how to handle this with Adobe DTM/Analytics. Each page can have between 1 and n tags being captured in an array. I can see them in the developer console just fine, ex:
> data.page.termIds
< [513, 1787, 115, 4330]
Each element corresponds to the tag ID.
I've been searching online but can't find any answers that really help me. This blog post is close, but it looks like they need to create a separate data element for each element in the array. I also found this question in the adobe forums, but it's similar to the blog post.
Does anyone know if this is even possible? Are we expected to create a block of data elements, with each one assigned to an array index?
Do not bother with the JS Object option unless you want to target a top level js object/variable. So for example foobar is okay but foo['bar'] or foo.bar is not. If you want to target anything "nested", skip JS Object and use Custom Script to check for it and return it, instead. This is because DTM doesn't do a good job of parsing or checking if the parent nodes exist before returning it. This is basically what was already said in the blog link you mentioned.
As for what the Data Element is returning and how to use it...the Data Element itself will have a return value of exactly what you return. So if you return an object, it will be an object. If you return an array, it will be an array. The trick (or caveat, or bug, depending on how you want to look at it) is how you reference or use the Data Element within the tools and rules.
The long story short of it is this: If you intend to use the %data_element_name% syntax (e.g. in any of the built in form fields in the rules, config settings, etc.) then you should only have your Data Element return a string type value (this is basically the issue the forum post link had, and I assume the issue you are running into).
If you want to be able to access it as some other type (e.g. the array, or js object in general), you need to use _satellite.getVar('data_element_name') syntax. The obvious drawback to this is it basically makes using DTM in a "non-coder" way useless in that you cannot use this in any of the built-in fields in rules. You can only use it in contexts where you can write javascript, e.g. Data > Custom type Conditions or in Javascript / 3rd Party Tag containers.
But one question for you is, what are you ultimately using the Data Element for? For example, if the end game here is you are looking to populate a prop or eVar or some other variable with a comma delimited string.. well just return your array as such in your Data Element and then you can use the %data_element_name% syntax.
Capturing the data is one thing and formatting is another.
My question is how do you need to see this data organized in reporting? Capturing the array itself doesn't do much unless you know what format you need it in. Are you hoping to capture these IDs and classify them? Do you want to see the array list by page?
Can you provide more detail on how you'll be reporting on these values?

Categories