I have a use case where I want to assign unique ids to each element of array while iterating over it. Note, This array contains duplicate values. I want to use index as a key in react element, but linter rules do not allow me to use index as a key.
I thought of using System tics. Is there a way I can get system ticks so that on every instruction execution, I get a new value?
If yes, what is the recommended precision?
I would suggest to use neither indices nor system ticks as both options take you away from the functionality that the key is supposed to provide.
In the documentation it says: "Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity"
So there are a variety of options:
You can create a function to generate unique keys/ids/numbers/strings and use that
You can make use of existing npm packages like uuid, uniqid, etc
You can also generate random number like new Date().getTime(); and prefix it with something from the item you're iterating to guarantee its uniqueness
Lastly, you can use the unique ID you get from the database, if you get it (hard to say without seeing your data)
However: Keys should be stable, predictable, and unique. Unstable keys (like those produced by Math.random()) will cause many component instances and DOM nodes to be unnecessarily recreated, which can cause performance degradation and lost state in child components.
You can read more here: https://reactjs.org/docs/reconciliation.html#keys
So there is no perfect answer for that. It depends on your use case...
Even though #Archer 's approach might already be feasible enough, I provide this solution that I mostly use in cases like the ones described by the OP ...
var createId = (
/* [https://github.com/broofa/node-uuid] - Robert Kieffer */
(window.uuid && (typeof window.uuid.v4 === 'function') && window.uuid.v4)
/* [https://gist.github.com/jed/982883] - Jed Schmidt */
|| function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,b)}
);
console.log('createId() : ', createId());
console.log('createId() : ', createId());
console.log('createId() : ', createId());
.as-console-wrapper { max-height: 100%!important; top: 0; }
Related
Set and Map both are newer data types in es6 and for certain situations both can be used.
e.g - if i want to store all unique elements, i can use Set as well as Map with true as value.
const data: string[] ;
// console.log('data', data[0])
const set = new Set();
const map = new Map<string, boolean>();
data.forEach((item) => {
map.set(item, true);
});
data.forEach((item) => {
set.add(item);
});
Both works, but i was wondering which one is faster ?
Update 1
I am looking for which of the data structure is faster in case of storing data.
checking if value exist using -
map.has(<value>)
set.has(<value>)
deleting values
Also i can understand true is redundant and not used anywhere, but i am just trying to show how map and set can be used alternatively.
What matters is speed.
In the most basic sense:
Maps are for holding key-value pairs
Sets are for holding values
The true in your map is completely redundant ... if a key exists, that automatically implies, that it is true/exists - so you will never ever need to use the value of the key-value pair in the map (so why use the map at all, if you're never gonna make use of what it is actually for? - to me that sounds like a set/array with extra steps)
If you just want to store values use an array or set. - Which of the two depends on what you are trying to do.
The question of "which is faster" can't really be answered properly, because it largely depends on what you are trying to do with the stored values. (What you are trying to do also determines what data structure to use)
So choose whatever data structure you think fits your needs best, and when you run into a problem that another would fix, you can always change it later/convert from one into another.
And the more you use them and the more you see what they can and can not do, the better you'll get at determining which to use from the start (for a given problem)
Say you have a very simple data structure:
(personId, name)
...and you want to store a number of these in a javascript variable. As I see it you have three options:
// a single object
var people = {
1 : 'Joe',
3 : 'Sam',
8 : 'Eve'
};
// or, an array of objects
var people = [
{ id: 1, name: 'Joe'},
{ id: 3, name: 'Sam'},
{ id: 8, name: 'Eve'}
];
// or, a combination of the two
var people = {
1 : { id: 1, name: 'Joe'},
3 : { id: 3, name: 'Sam'},
8 : { id: 8, name: 'Eve'}
};
The second or third option is obviously the way to go if you have (or expect that you might have) more than one "value" part to store (eg, adding in their age or something), so, for the sake of argument, let's assume that there's never ever going to be any more data values needed in this structure. Which one do you choose and why?
Edit: The example now shows the most common situation: non-sequential ids.
Each solution has its use cases.
I think the first solution is good if you're trying to define a one-to-one relationship (such as a simple mapping), especially if you need to use the key as a lookup key.
The second solution feels the most robust to me in general, and I'd probably use it if I didn't need a fast lookup key:
It's self-describing, so you don't
have to depend on anyone using
people to know that the key is the id of the user.
Each object comes self-contained,
which is better for passing the data
elsewhere - instead of two parameters
(id and name) you just pass around
people.
This is a rare problem, but sometimes
the key values may not be valid to
use as keys. For example, I once
wanted to map string conversions
(e.g., ":" to ">"), but since ":"
isn't a valid variable name I had to
use the second method.
It's easily extensible, in case
somewhere along the line you need to
add more data to some (or all) users.
(Sorry, I know about your "for
argument's sake" but this is an
important aspect.)
The third would be good if you need fast lookup time + some of the advantages listed above (passing the data around, self-describing). However, if you don't need the fast lookup time, it's a lot more cumbersome. Also, either way, you run the risk of error if the id in the object somehow varies from the id in people.
Actually, there is a fourth option:
var people = ['Joe', 'Sam', 'Eve'];
since your values happen to be consecutive. (Of course, you'll have to add/subtract one --- or just put undefined as the first element).
Personally, I'd go with your (1) or (3), because those will be the quickest to look up someone by ID (O logn at worst). If you have to find id 3 in (2), you either can look it up by index (in which case my (4) is ok) or you have to search — O(n).
Clarification: I say O(logn) is the worst it could be because, AFAIK, and implementation could decide to use a balanced tree instead of a hash table. A hash table would be O(1), assuming minimal collisions.
Edit from nickf: I've since changed the example in the OP, so this answer may not make as much sense any more. Apologies.
Post-edit
Ok, post-edit, I'd pick option (3). It is extensible (easy to add new attributes), features fast lookups, and can be iterated as well. It also allows you to go from entry back to ID, should you need to.
Option (1) would be useful if (a) you need to save memory; (b) you never need to go from object back to id; (c) you will never extend the data stored (e.g., you can't add the person's last name)
Option (2) is good if you (a) need to preserve ordering; (b) need to iterate all elements; (c) do not need to look up elements by id, unless it is sorted by id (you can do a binary search in O(logn). Note, of course, if you need to keep it sorted then you'll pay a cost on insert.
Assuming the data will never change, the first (single object) option is the best.
The simplicity of the structure means it's the quickest to parse, and in the case of small, seldom (or never) changing data sets such as this one, I can only imagine that it will be frequently executed - in which case minimal overhead is the way to go.
I created a little library to manage key value pairs.
https://github.com/scaraveos/keyval.js#readme
It uses
an object to store the keys, which allows for fast delete and value retrieval
operations and
a linked list to allow for really fast value iteration
Hope it helps :)
The third option is the best for any forward-looking application. You will probably wish to add more fields to your person record, so the first option is unsuitable. Also, it is very likely that you will have a large number of persons to store, and will want to look up records quickly - thus dumping them into a simple array (as is done in option #2) is not a good idea either.
The third pattern gives you the option to use any string as an ID, have complex Person structures and get and set person records in a constant time. It's definitely the way to go.
One thing that option #3 lacks is a stable deterministic ordering (which is the upside of option #2). If you need this, I would recommend keeping an ordered array of person IDs as a separate structure for when you need to list persons in order. The advantage would be that you can keep multiple such arrays, for different orderings of the same data set.
Given your constraint that you will only ever have name as the value, I would pick the first option. It's the cleanest, has the least overhead and the fastest look up.
I've recently started with Reactjs and I find it really interesting. Keys are about identity, so identifying each component through a unique key is the way to go, right?
Suppose I have this example:
var fruits = [
{'fruitId': 351421, 'fruit': 'banana'},
{'fruitId': 254134, 'fruit': 'apple'},
{'fruitId': 821553, 'fruit': 'orange'}
];
React.DOM.ul(null, fruits.map(function(item) {
return (
React.DOM.li({
key: item.fruitId
}, item.fruit)
);
}));
Note the big IDs numbers. Now, my question is if is better to use numbers as IDs or strings like a hashes as IDs?
Thanks!!
It really doesn't matter, the only thing that matters is that the key is unique among siblings within the parent element. It doesn't have to be unique across your entire app, just inside the parent you're appending these items to.
Often for simple iteration over elements, such as <li> or <option> it's fine to just use the index within your iterator.
EG:
var options = [];
for (var i=0; i<this.props.options.length; i++) {
var option = this.props.options[i];
options.push(
<option key={i} value={option.value}>{option.name}</option>
);
}
The only time this doesn't work well is if you are adding/removing keyed elements in different orders etc later on so that your key might clash with another sibling. In which case you're going to want to generate the key in some other way to make sure it's unique - or use a known unique key from your model. Whichever way you do it as long as it's unique among it's siblings, it'll be fine.
As #Mike says, they are only used to preserve the ordering of the real DOM elements if your are adding to/removing from a list. They only need to be unique to the local component, so it's ok to reuse natural ids from your data. I would not use an index from an iterator because of this.
Re. numbers, vs strings: if you're concerned about performance, I'd use whatever type you've already got. Any conversion/parsing you do will be done on every render. However, this would be pretty low on my list of performance concerns in my app.
I was remembering that there was a jquery method which provide unique number for dom elements. It just may for only animated dom objects. Now I couldn't find that method. What is that method ? Is there any another way to provide unique number for elements ?
I think you may be thinking about the concept of jQuery.expando. There is an attribute called jQuery.expando that exists on every page that has jQuery running. It is defined like this:
expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
So for me, on the current page, it is jQuery15209244967177268291. Any element that has any data stored on it (including event handlers, which are stored as data) has a property with that name. This contains a unique number, which is the key for that element in the global data cache.
For instance, with the global StackExchange inbox on the top left of the screen:
$('.genu')[0].jQuery15209244967177268291 === 29
You can mimic this with $('.genu')[0][jQuery.expando]; I'm not sure whether you'll get the same number. (Edit: it's not even the same number for me every time.)
Note, however, that not every element has a unique number, only those with data attached to them. This may or may not fit your purposes...
The only thing that looks remotely like what you might be after is the jQuery.unique(), but even that doesn't do what you're suggesting. I would encourage you to update your question to state the purpose for this, as there may be a better way to solve the problem that is prompting you to get unique numbers for each element.
Java has LinkedHashMap which gets you 99% there to an LRU cache.
Is there a Javascript implementation of an LRU cache, preferably from a reputable source, that is:
understandable
efficient (amortized O(1) get/put/delete)
? I've been searching on the web but couldn't find one; I thought I found one on Ajax Design Patterns but it glosses over the sendToTail() method and has O(n) performance (presumably, since the queue and associative array are split up).
I suppose I could write my own, but I've learned the hard way that reinventing the wheel for core algorithms can be hazardous to one's health :/
Map should be O(1) in most implementations average case. Since Map keeps insertion order, adding a bit of code around it will get you a LRU and for most uses this should be plenty fast.
I needed a simple LRU cache for a small number of expensive operations (1 second). I felt better about copy-pasting some small code rather than introducing something external, but since I didn't find it I wrote it:
class LRU {
constructor(max = 10) {
this.max = max;
this.cache = new Map();
}
get(key) {
let item = this.cache.get(key);
if (item) {
// refresh key
this.cache.delete(key);
this.cache.set(key, item);
}
return item;
}
set(key, val) {
// refresh key
if (this.cache.has(key)) this.cache.delete(key);
// evict oldest
else if (this.cache.size == this.max) this.cache.delete(this.first());
this.cache.set(key, val);
}
first() {
return this.cache.keys().next().value;
}
}
Usage:
> let cache = new LRU(3)
> [1, 2, 3, 4, 5].forEach(v => cache.set(v, 'v:'+v))
> cache.get(2)
undefined
> cache.get(3)
"v:3"
> cache.set(6, 6)
> cache.get(4)
undefined
> cache.get(3)
"v:3"
This:
https://github.com/monsur/jscache
seems to fit you case although setItem (i.e. put) is O(N) in the worst case, that happens if the cache is filled up on insertion. In this case the cache is searched to purge expired items or least recently used items. getItem is O(1) and the expiry is handled on the getItem operation (i.e. if the item being fetched is expired, removes it and returns null).
The code is compact enough to be easily understood.
P.S. It might be useful to add to the constructor the option to specify the fillFactor, which is fixed to 0.75 (meaning that when the cache is purged it's size is reduced at least to 3/4th of the maximum size)
This is worth a mention:
https://github.com/rsms/js-lru
The core set of functions are O(1) and the code is heavily commented (with ASCII art too!)
The monsur.com implementation is O(n) on insertion only because it has items which actually expire on real world time. It is not a simple LRU. If you only care about maintaining the most recently used items without regard to real world time, this can be done in O(1). A queue, implemented as a doubly linked list, is O(1) for insertion or deletion from the end, and this is all you should need for a cache. As for lookup, a hash map, which javascript makes pathetically easy, should be good for nearly O(1) lookup (assuming the javascript engine uses a good hashmap, that's implementation dependent of course). So you have a linked list of items with a hash map pointing to the items. Manipulate the ends of the linked list as needed to put new items and requested items on one end and remove old items from the other end.
This library runtime-memcache implements lru and a few other caching schemes in javascript.
It uses modified Doubly Linked List to achieve O(1) for get, set and remove. You can check out the implementation which is pretty simple.
It's not an LRU cache, but I've got my own linked map implementation. As it uses a JS objects as store, it'll have similar performance characteristics (the wrapper objects and hash function impart a performance penalty).
Currently, documentation is basically non-existant, but there's a related SO answer.
The each() method will pass the current key, the current value and a boolean indicating if there are more elements as arguments to the callback function.
Alternatively, looping can be done manually via
for(var i = map.size; i--; map.next()) {
var currentKey = map.key();
var currentValue = map.value();
}
I am aware that this is an old question but adding a link for future refrence.
Check out https://github.com/monmohan/dsjslib . This has a LRU Cache implementation in addition to some other data structures. Such caches (and this one too) maintain doubly linked list of cache entries in LRU order i.e. entries move to the head as they are accessed and are removed from tail when they are reclaimed (say by expiry or because size limit was reached). Its O(1) since it only involves constant number of pointer manipulations.
I improve #odinho's answer to fit this leetcode question
change if (item) to if (item != undefined) to fit value === 0 case
following is my code:
class LRUCache {
constructor(max = 10) {
this.max = max
this.cache = new Map()
}
get(key) {
let item = this.cache.get(key)
if (item !== undefined) {
// refresh key
this.cache.delete(key)
this.cache.set(key, item)
}
return item === undefined ? -1 : item
}
put(key, val) {
// refresh key
if (this.cache.has(key)) this.cache.delete(key)
// evict oldest
else if (this.cache.size == this.max) this.cache.delete(this.first())
this.cache.set(key, val)
}
first() {
return this.cache.keys().next().value
}
}
Since we need read, write, update and delete operations in O(1), we use two data structures.
An Object(or Map)in JavaScript provides retrieval in O(1).
A Doubly LinkedList(Custom data structure we create) makes below functionalities in O(1)
change position of the most used element to the top
delete least used element from cache on reaching cache limit.
The custom implementation of Doubly LinkedList and Least Recently Used cache with clear explanation is given below.
https://medium.com/dsinjs/implementing-lru-cache-in-javascript-94ba6755cda9
External package/library is not required, we can write our own code to implement LRU in javascript, Please refer https://dev.to/udayvunnam/implementing-lru-cache-in-javascript-3c8g site for details.