Javascript Map does not contain array of numbers as key - javascript

I'm trying to create a map based on certain arrays of three. For example,
const rule30Map = new Map();
rule30Map.set([1, 0, 0], 1);
rule30Map.set([0, 1, 1], 1);
rule30Map.set([0, 1, 0], 1);
rule30Map.set([0, 0, 1], 1);
When I try getting a value based on values in an array, the console returns undefined,
console.log(rule30Map.get([1, 0, 0])); // prints undefined
but the expected output would be 1. Can somebody explain why my logic was misunderstood?

The keys are compared with === comparison. Two separate arrays that look like [1, 0, 0] are still two separate arrays that are not equal to each other.
Working out some automated way of keeping track of key objects by their characteristics somehow would probably be more complicated than using a plain object for storage. Because JavaScript does not provide a generic way for a class of objects to supply hashing and comparison overrides means that Map and Set in JavaScript are somewhat limited in usefulness.

You could do:
const a = [1,0,0];
const map = new Map();
map.set(a.toString(), "value");
map.get([1,0,0].toString());
I assume you are computing the [1,0,0] part.

Related

I wanna understand sort function working in javascript [duplicate]

This question already has answers here:
How to sort an array of integers correctly
(32 answers)
Sort number javascript array
(2 answers)
Closed 4 months ago.
If array A = [-1, -3, -2, 0];
if I try to sort it
like A.sort()
console.log(A)
return is [-1, -2, -3, 0] instead of [-3, -2, -1, 0]
The Array.prototype.sort accepts an optional callback function (a compare function) that you use to sort the array based on your preference.
In your example above, you didn't specify a compare function thus sort will default to:
sorting the elements of an array in place and returns the reference to the same array, now sorted. The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values. Source: MDN
From the result sample you included, it seems you want to sort those numbers in an ascending order (smaller to bigger). To do so, you should pass a compare function to the sort method that describes that sorting logic you'd want to have.
Here's a live demo:
const myArray = [-1, -3, -2, 0];
/** Please check the linked docs page for more details */
console.log(myArray.sort((a, b) => a < b ? -1 : 1)); // or simply: "(a, b) => a - b)"
The above demo should print: [-3, -2, -1, 0].
You can do this:
A.sort((a, b) => a-b);

Is there any way of converting OpenCV.Mat to array in JavaScript?

I'm working on Mat in OpenCV. However, I need to manually calculate the Mat by myself. Is there is a way of accessing Mat likes 2D array?
const myMat = cv.matFromArray(cv, 3, 3, cv.CV_64F, [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
])
const newMat = someProcessThatReturnMat(myMat)
/* OpenCV in JS cannot access Mat like this */
const result = someProcess(newMat[1][2], newMat[2][0])
Thank you in advance
Updated: The problem is cv.matFromArray cannot convert 2D array to Mat. You have to use it as 1D array. That's why it never return the correct values. For example:
const myMat = cv.matFromArray(3, 3, cv.CV_64F, [1,2,3,4,5,6,7,8,9])
And then, you can access the value
const value = myMat.doubleAt(1, 2) // row 1, col 2
You need to use the doubleAt(y,x) method.
It's double because the mat's content is CV_64F, not because you want doubles.
You can also use .data64F to access a flat Float64Array of the Mat's data.
OpenCV.js is... rough. It originated from someone's Google Summer of Code and hasn't received significant care since. Documentation amounts to some tutorials; API docs seem to be missing entirely. The "Mat" interface emulated the at() method from C++, badly, instead of looking at numpy (python) or making this access feel "native" to javascript. Overloading the [] operator is possible using a Proxy but that was not implemented.
Here's an example: https://docs.opencv.org/4.x/de/d06/tutorial_js_basic_ops.html
Feel free to browse OpenCV's issues and maybe suggest some improvements.

Which way of iterating array and changing element by map is more efficient?

I have a question about map.As you know by using map we can iterate arrays and able to change the element of arrays.To do that there are two ways and I listed them below.Which way has less complexity and more performance?(In the examples arrays are not big but think about the real world like 500 elements in an array)
var numbers = [4, 9, 16, 25];
numbers=numbers.map(e=>{
return e=e*2;
})
In this approach assigning each returned value to current array.
numbers.map((e,a)=>{
numbers[a]=e*2;
})
In this one on each iteration we need to go to array by index to find element and I think this is worse than above but Im not sure.
Don't use map if you're not going to use the array it creates. If you just want to loop through an array, use a loop or forEach or similar.
Whether you want a new array or not, the most efficient way to loop through an array is usually a for loop:
const numbers = [4, 9, 16, 25];
for (let i = 0, len = numbers.length; i < len; ++i) {
numbers[i] = numbers[i] * 2;
}
(Or any of several variations on that.)
But "most efficient" is extremely unlikely to actually matter in real-world code, so using things like map (if you want a new array) or forEach (if you don't) is just fine. map is idiomatic for that operation (creating a new array containing the entries from a previous array modified in some way).
Conclusion:
If you want a new array, feel free to use map, or create a blank array and use any of your options for looping arrays to loop the original and add entries to the new one.
If you don't want a new array, don't use map, use any of your options for iterating over the original except for ones that don't give you the index, and assign the updated value back to the entry.
Semantically you need for or forEach when you do not need a new array.
For sufficiently small arrays there is no difference in performance
var numbers = [4, 9, 16, 25];
numbers.forEach((e,i)=> numbers[i] = e*2);
console.log(numbers)
nums.forEach((v, i) => nums[i] = v);
is the fastest method possible that you listed (equivalent to your second method. Why? nums = nums.map(...) creates an entire copy of the array in memory and replaces the array with that copy. When you simply iterate over the array with an index and replace elements, you avoid making that copy, and it ends up being around 15% faster (see this benchmark.
The fastest way to change a value of an array is to iterate the index and update the item.
This approach is faset than forEach or map, because it does not have the overhead of this and it does not need the feature of the supplied structure of the callback.
var numbers = [4, 9, 16, 25];
for (let i = 0; i < numbers.length; i++) numbers[i] *= 2;
console.log(numbers);

In what cases do javascript developers use the map() method?

I'm learning about the map() method right now and I understand very basic examples.
var numbers = [2, 4, 6];
var double = numbers.map(function(value) {
return value * 2;
});
My question is, in what cases do developers use the map() method to help solve problems? Are there some good resources with real world examples?
Thanks for the help!
As #Tushar referred:
The map() method creates a new array with the results of calling a
provided function on every element in this array.
So it is basically used when you need to apply certain functionality to every single element of an array and get the result back as an array with the new results.
For example doubling the numbers:
var numbers = [1, 4, 9];
var doubles = numbers.map(function(num) {
return num * 2;
});
// doubles is now [2, 8, 18]. numbers is still [1, 4, 9]
It basically helps to shorten your code eliminating the need of using for loop. But do remember it is used when every element of the array is manipulated because map() generates similar length of array provided.
For eg.- in the example you provided doubles will have [2, 8, 18].
where 2 correspond to 1.
4 correspond to 8.
9 correspond to 18.
I recommend you to watch the whole video but your answer is at the 14th minute:
Asynchronous JavaScript at Netflix by Matthew Podwysowski at JSConf Budapest 2015

Fastest way to reset a multidimensional array?

Say I have a two dimensional array: vectors[x][y], and the initial array structure looks like this:
vectors = [
[0, 0, 0, 0, 0,],
[0, 0, 0, 0, 0,],
[0, 0, 0, 0, 0,],
[0, 0, 0, 0, 0,],
[0, 0, 0, 0, 0,]
]
After some calculations, the data in the array is randomized. What is the fastest way and most efficient way to return the array to it's initial state?
I know that I could just hardcode the above zeroed array and set vectors equal to it again, but I also know that an algorithm such as:
for (var x = 0; x < vectors.length; x++) {
for (var y = 0; y < vectors[x].length; y++) {
vectors[x][y] = 0;
}
}
is O(x * y).
So which is the better way? And is there a better, even faster/more efficient way to solve this?
And for the general case of zeroing a multi-dimensional array of any length, which is the best way? (I'm working in JavaScript if it matters)
Here is my two cents:
I'd go with keeping a clean copy of your original array for fastest performance. You can either keep a referenced hard-coded copy
var vectorsOrig = [
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]
];
or do a dynamic clean clone of the initial array using slice ((recursively in your case for deep copy):
var clonedVectors = [0, 0, 0, 0, 0].slice(0);
Regardless, taking the approach of resetting your vector reference to an original copy will be faster than cycling through and resetting each node. If your old vector array object isn't referenced any more, JavaScript will garbage collect it.
With that said, the question becomes of obtaining a clean copy each and every time. Having once hard-coded instance will give you one clean copy and you'll have to clone it thereafter. Nor do you want to into dynamic generation via similar for loops as the reset option. My advice is to write a clone function that simply returns a new hard-coded or initialized array:
function newVector() {
return [
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]
];
}
var vector = newVector();
vector[1][2] = 11;
console.dir(vector);
vector = newVector(); // your old array will be garbage-collected if no longer referenced by any other reference
console.dir(vector);
Ideally, it's best to benchmark various approach.
EDIT
Thanks to Vega's input, I've modified his test to test three approaches. In Chrome and IE9, this solution seems to be the fastest, in FF (15.0.1) manual iteration seems faster (memory allocation/management slower in FF possibly). http://jsperf.com/array-zero-test/2
So far, it sounds like we have 2 possible choices.
Overwrite the whole thing with zeroes. (Your solution)
Keep a record of all modified elements and only reset those ones. record[0].x = 3; record[0].y = 5; and so on
However, you'll still need to loop once through the record. To explain it further, I mean that each time an element in the array is set to a value, you should record that element's placement in the array. Then, using a loop, you can visit each element and set it to 0. So, if you had a sparse array, it would be more efficient.
Depending on the implementation, I can see why you would want #2 instead of #1...but if you seriously have a large enough matrix that you need to worry about analyzing the algorithm, you might consider doing some kind of server pre-processing.
Another different way of looking at the problem is to use a linear array and calculate the linear index from the x, y indices when you do your updates.
The initialization is then just a single for loop with time O(x+y)
I'll risk and say that the fastest way of assigning the same value to all elements is by calling Array.map().
But, there is a catch here. Note that this will have incredibly fast performance on browsers that have natively implemented that method, and will have just the usual performance in other browsers. Also note that .map() isn't available in some old browsers, so you'll need to use Underscore.js or any other library that provides that method.

Categories