I have a grid of values, represented by a two-dimensional array.
Here is a literal representation of the data: dataValues[row][column]
So dataValues[3][0] would be the fourth row, first column.
Well, I need to search the first column of every row for a value and I'm looking for the least computational intensive way of doing that.
I know I can do it with a loop:
for (var i in dataValues) {
if (dataValues[i][0] == "Totals") {
matchingRow = i;
break;
}
}
But I like to avoid loops wherever possible and I can't think of a way to apply Array.prototype.indexOf in a useful way here.
Is there even a computational difference between a loop and indexOf? It seems to me that indexOf would probably just run its own loop.
You can use Array#find() which will break once condition is met and return first matching element or return undefined if condition is not met
let matchingItem = dataValues.find(arr=> arr[0] == "Totals");
if(matchingItem ){
// do what you want with matching elemnt of dataValues
}
Related
I'm learning Javascript, so pardon any mistakes in how I phrase the question.
I am writing a chess program to practice and learn. Currently, I am trying to write a function to find the color of a piece with the position as the parameter. The relevant pieces of code are as follows. The first two work as they were designed to, but the last does not.
let allPieces = board.getElementsByClassName('piece');
This sets allPieces as an object with the key values the html elemnts representing each piece, both black and white.
const getPiecePosition = function(element) {
let position = window.getComputedStyle(element).getPropertyValue('grid-row-start');
let letterIndex = alphabet.findIndex(function(letter) {
return letter === position[0];
});
letterIndex += 1;
return [letterIndex, Number(position[1])];
}
This takes a parameter in the form of the allPieces object with a specific key and returns the position as an array with the column number first and the row number second. ex. [2,3].
const getPieceByPosition = function(position) {
let pce = Object.keys(allPieces).forEach(function(piece) {
if (getPiecePosition(allPieces[piece]) == position) {
return allPieces[piece].borderColor;
}
})
return pce;
}
This is the function I am having trouble with. The idea behind it is that it will take each key in the allPieces object and loop through them using forEach() into the getPiecePosition() function to compare it with the position entered as the parameter. Since only one piece can inhabit any tile at once, it should never return multiple values.
I honestly don't know where to start debugging this code, but I have been trying for about an hour. It always just returns undefined instead of a truthy value of any kind.
Your last function has a few issues:
getPiecePosition(allPieces[piece]) == position
Assuming position is an array, you're trying to compare an array with an array here using ==. However, since the two arrays are different references in memory, this will always give false, even if they contain the same elements:
console.log([2, 3] == [2, 3]); // false
You're trying to return from the callback of .forEach(). This won't achieve what you want, as return will jump out of the .forEach callback function, not your outer getPieceByPosition() function. This leads me to your final issue:
The .forEach() method doesn't return anything. That is, it doesn't evaluate to a value once it is called. This means that let pce will always be undefined since you're trying to set it to the return value of .forEach(). This, in contrast to let letterIndex, is different, as letterIndex is set to the return value of .findIndex(), which does have a return value and is determined by the function you pass it.
One additional thing you can fix up is the use of Object.keys(allPieces). While this works, it's not the best approach for looping over your elements. Ideally, you would be able to do allPieces.forEach() to loop over all your elements. However, since allPieces is a HTMLCollection, you won't be able to do that. Instead, you can use a regular for loop or a for..of loop to loop over the values in your HTMLCollection.
Alternatively, there is a way to make allPieces.forEach() work.
Instead of using board.getElementsByClassName('piece');, you can use the method .querySelectorAll('.piece'), which will give you a NodeList. Unlike a HTMLCollection, a NodeList allows you to use .forEach() on it to loop through its elements.
The return type of getElementsByClassName HTMLCollection Object. You should't use Object.keys to loop through each of 'piece' element. Insted, use the follow.
for(var i = 0 ; i < allPieces.length ; i++){
var piece = allPieces[i];
... // and, do whatever with the getPiecePosition(piece)
}
I have an array which consists of one cell which holds a string.
var myArray = ["hopefully i will get an answer to this problem"]
Trying to loop through the array itself isn't bearing any fruit as i am not used to working with only one cell.
for(var i=0; i<myArray.length; i++) {
console.log(myArray[i]);
} //returns the whole string "hopefully i will get an answer to this problem"
//this would allow me to loop through many cells in one array but here i only have one cell in one aray
Now i would like to do something with the first letter of each word.
But as i said above, the typical array iteration i am used to doing is often working with many cells not a single cell.
My Question then is as follows:
Given this array with a single cell
var myArray = ["hopefully i will get an answer to this problem"]
What is the best way to get hold of the first letter of each word to do something to it.
NOTE:
If it helps you to form an answer I actually need to capitalize the first letter of every word
You have an array with 1 element in it. You first loop makes only one iteration and outputs this first element.
I believe what you want to do is the following:
for(var i=0; i<myArray.length; i++) {
if(myArray[0][i] === " "){
//do some code with myArray[i]
}
}
There are a few things to point out here:
1) You don't need the array to loop over a string
JS strings act as an array of characters on their own, so you can indeed loop over them. In your example however, you're looping over the outer array, which holds only one element, so its length is 1. This means that the line
for(var i=0; i<myArray.length; i++) {
combined with the fact that you decrement i by 1 later here
console.log(myArray[i-1])
means that your function loops from -1 (i-1) and ends when it reaches 0 (i<1). As myArray[-1] is undefined, that's where your result comes from.
If you remove the outer array, your approach would work with just the string.
2) A loop isn't always the best for string manipulation
Then again, there are better ways to achieve what you're trying to do. JS has built-in functions for splitting a string into an array of words and joining an array of strings into a string. Combine that with your approach to loop over single words or charAt() to find individual characters by their index and you can make your code a lot more straightforward.
Also, take a look at the built-in methods and properties of Strings that can make your life easier, such as toUpperCase() and toLowerCase().
Hope this helps!
there are may more than one spaces in the empty item of array. So before match you can clear all of spaces like this
for(var i=1; i<myArray.length; i++) {
if(myArray[i-1].toString().replace(/\s/g,'') === ''){
//do some code with myArray[i]
}
}
or
for(var i=1; i<myArray.length; i++) {
if(!myArray[i-1].toString().replace(/\s/g,'')){
//do some code with myArray[i]
}
}
myArray.length = 1 so don't use array the for can't traversal this , use string
So here's my problem:
So this is what my array looks like, I have shown a fragment of it here (from the console window).
It's overall pretty basic right? Except for it's indexing. As you see the first has value "1" and let's say the second has value "4". As for it's subarrays, these have custom indexes too.
Therefore, the old fashioned:
for(i=0; i<array.length; i++){
someVar = array[i];
//do something
}
won't work.
I get the 1 or 4 from iterating through another array, so don't need to get those.
I want to get all subArrays(not the further nested subArrays, only the second level).
So basicly what I want is something like this(is there something like this?):
array[someIndex].children.forEach(
//do something with **this**
)
To make it more practical for you:
So I know that the first array has index 1. How can I get the values of cat1 and cat2 without knowing it has index 2 (this could also be 6 or 42 for example). In this case, the first array only has one subArray but I would like to make it work for multiple subArrays. (to clarify, select cat1, cat2 from the second level subarray with, in this case, index 2)
Thanks in advance, any help is appreciated!
Evoc
Those aren't arrays. You have
[ { "1": { etc...
which is an array containing an object containing multiple other objects. You can't really use a for(i=...) loop for this, because your keys aren't sequential. You should use a for ... in loop instead:
arr = [{"1":{....}}];
for (i in arr[0]) {
for (j in arr[0][i]) {
console.log(arr[0][i][j]['msg']);
}
}
Use Object.getOwnPropertyNames to get the properties ordered with the integer indices first, from smallest to greatest. Iterate them to get msg1.
var array = {"1":{"3":{"5":{"data":"someData","moreData":"someMoreData"},"msg1":"hello world","msg2":"foo equals bar"},"5":{"8":{"data":"someData","moreData":"someMoreData"},"msg1":"world hello","msg2":"bar equals foo"},"your_name":"jimmy","your_msg":"hello world"},"4":{"3":{"5":{"data":"someData","moreData":"someMoreData"},"msg1":"hello world","msg2":"foo equals bar"},"5":{"8":{"data":"someData","moreData":"someMoreData"},"msg1":"world hello","msg2":"bar equals foo"},"your_name":"billy","your_msg":"foo equals bar"}};
for(let key of Object.getOwnPropertyNames(array[1])) {
if(Object(array[1][key]) !== array[1][key]) break;
console.log('msg1 of "'+key+'": ' + array[1][key].msg1);
}
console.log('your_msg: ' + array[1].your_msg);
The example you showed it's an array with only one index, inside of this index there are nested objects, you could iterate them using the property iterator (foreach). You have to go to the second level tho, since the values you need are there.
for (var key in object) {
for(var anotherKey in object[key]) {
//check for undefined
if(object[key][anotherKey].hasOwnProperty('msg')) {
//code
}
}
}
{ } - declaring objects (literal)
[ ] - declaring arrays
I know the classic way of looping through an array arr is:
for(var i=0 ; i<arr.length ; i++) {
// code
}
But someone recently showed me a different way of implementing the condition inside that loop, like this:
for(var i=0 ; arr[i] !== undefined ; i++) {
I think this solution is interesting because this is exactly what you need when you loop through an array: you don't want to get undefineds when you try to access an undefined index.
I realize that if you count the characters it looks longer, and also that you might have some problems with arrays like this: ["Hello", , "World"], but apart from that - is there anything else I'm missing here? Why shouldn't we be using this technique instead?
Why shouldn't we be using this technique instead?
It doesn't work on sparse arrays (as you mentioned)
It doesn't work on arrays that contain undefined values
It's not as easily optimised (assuming the .length stays constant during the loop)
(In the old days, the undefined identifier could be overwritten, you'd need to use typeof)
Of cource, wheter it "works" for you depends on the use case, and sometimes you might want to use it. Most times, you simply don't.
And even if both ways would work in your case, it's better practise to use the standard approach (i<arr.length) as there is lower mental overhead. Everyone recognises that pattern and knows what it does, while with arr[i]!==undefined one would need to think about why the uncommon approach was chosen.
Sometimes arrays have empty values and your way of iteration will fail.
var arr = [];
arr[5] = 5;
for (var i = 0; arr[i] !== undefined; ++i) {
console.log(arr[i]);
}
console.log('done');
If you want to iterate real array values and skip undefined's, i suggest you to filter the array first and do iteration after. So your code will be more understandable. Example:
var arr = [];
arr[5] = 5;
arr.filter(Boolean).forEach(function (e) {
console.log(e);
});
console.log('done');
I need a script to search efficiently all the duplicates in a one-dimensional array.
I tried a naive method :
for(var i=0, ii<arr.length-1; i<ii; i++)
for(var j=i+1, jj<arr.length; j<jj; j++)
if(arr[i] == arr[j])
// remove the duplicate
Very simple but it takes a too long time if the array contains a large set of values. The tables that I use often contain hundreds of thousands of values, so that the number of iterations required for this operation is HUGE !
If someone has an idea !?
Use a LinkedHashSet or OrderedHashSet implementation, it does not allow duplicates and provides expected O(1) on insertion, lookup, and deletion. Since your OP says you want to remove the duplicates, there is no faster way to do this than O(n). In an array of 1,000,000 items max time was 16ms
Create a LinkedHashSet hs
foreach object obj in arr
-- hs.add(obj);
Complexity is expected O(n) with a good hash function.
This code could be the most efficient way you can do it ..!! Which is nothing but the direct implementation of set .
function eliminateDuplicates(arr) {
var i,
len=arr.length,
out=[],
obj={};
for (i=0;i<len;i++) {
obj[arr[i]]=0;
}
for (i in obj) {
out.push(i);
}
return out;
}