Redefine array using itself - javascript

I wrote this solution to a problem I had, but I don't feel entirely comfortable with it. It seems to be dangerous, or at least in bad practice to use an array to redefine itself, sort of like trying to define a word but using the word in the definition. Can anyone explain either why this is wrong, or why it's ok?
let array = []
// other stuff happens to fill the array
array = array.filter(element => element !== true)
The reason I'm doing it this way is that I need that same variable name (array, for these purposes) to remain consistent throughout the function. The contents of the array might be added or removed multiple times before the array gets returned, depending on other behavior happening around it.
Let me know if this is too vague, I'll try to clarify. Thanks!

It's perfectly fine. The right side (array.filter(element => element !== true)) of the assignment will be evaluated first, generate a completely new array and only then it'll be assigned back into array.

You can loop through your array backwards and remove the items, as to not allocate another array and reassign.
for (i = array.length - 1; i >= 0; --i) {
if (!!array[i]) {
array.splice(i, 1);
}
}
This solution is:
Fast
Memory efficient
Will not interfere with any other code that has a reference to your original array.

Related

How to skip first iteration in javascript for-of loop

I know how to skip first iteration in javascript foreach loop
dataObject.slice(1).forEach((row) => {});
I want to know how to do the same thing using for of loop in javascript, please help me, thanks
for( const row of dataObject )
The same way you're skipping it with forEach - replace the dataObject expression with dataObject.slice(1).
for( const row of dataObject.slice(1) )
While CertainPerformace's solution is what most people, including me, would go with, it does have a the downside of having to make a temporary array copy, which would be bad when you have huge arrays (but completely unnoticeable usually).
To prevent copying the array, create a temporary variable to check if it's the first in the loop. The downsides of this is the temporary variable, and the if check on every iteration could make it slower.
let first = true;
for (const row of dataObject) {
if (first) {
first = false;
continue;
}
// ... rest of script
}
And I would probably just use a traditional incremental for-loop anyways if you want more control over iteration, since forEach, for-of, and for-in are meant to iterate over everything.

How to iterate through a linked list in javascript

Someone shared this beautifully elegant way to create a linked list from an array.
function removeKFromList(l, k) {
let list = l.reduceRight((value, next)=>({next, value}), null);
console.log(list);
}
let l = [3, 1, 2, 3, 4, 5];
let k = 3;
removeKFromList(l, k);
It's pretty easy to iterate arrays (for, filter, map, reduce, etc.) but a linked list has none of those features. I need to iterate through to remove k values from the list. I'm guessing I need to create a variable for the current node and use a while loop, but there's no documentation on this. I've seen some repl code doing it but it seems unnecessarily complicated.
How do you iterate through a linked list in javascript?
First of all, although the idea of using reduce is indeed beautiful, I must say that the result is not so good, because the resulting nodes have a field "next" where the value is and a field "value" where the next is, i.e. they are swapped. So let's fix that:
function removeKFromList(l, k) {
let list = l.reduceRight((value, next)=>({value: next, next: value}), null);
console.log(list);
}
Secondly, the name of that function is awful, it should be named "arrayToLinkedList" or something more suggestive. Also, logging the result does not make sense, we should return it instead. Moreover, the parameter k is simply unused. Fixing those things:
function arrayToLinkedList(array) {
return array.reduceRight((prev, cur) => ({ value: cur, next: prev }), null);
}
Now, let's work on how to iterate over this. What do you think? I will give some hints because giving the answer directly probably won't help you learn much:
Observe that the linked list itself is:
Either the value null, or
A plain object with two fields, one field "value" which can be anything, and one field "next" which is a linked list.
Observe that the above (recursive) definition is well-defined and covers all cases.
Now, use that to your assistence. How do you get the first value? That would be simply myList.value, right? Now how do I get the second value? By applying .next, we get the next linked list, and so on. If next is null, you know you have to stop.
Let me know if you need further assistance.
EDIT: I noticed that you're looking for the right way to make an iterating method on lists with an idea of "adding it to the prototype" or something. So, about that:
To add an instance method by a prototype, you'd need your linked lists to be a class. That would be overcomplicating, unless you really have a good reason to define a class for this (which would be creating several methods and utility things around it).
It is much better, in my opinion, to just define a function that takes one linked list as the first parameter and a callback function as the second parameter, similarly to lodash's .each:
function forEachValueInLinkedList(linkedList, callback) {
// here you loop through all values and call
// callback(value)
// for each value.
}
I'd say this would be the most "javascriptonic" way to do it.

How to find the first undefined array element in javascript, to fill it?

If entries are being added and removed in an array (not pushed/popped) what is the optimal way to scan and find the first undefined element, so that it can be set with a new value?
If the array contains holes with findIndex you can find the first one like so:
[1, 2,, 4, 5].findIndex(Object.is.bind(null, undefined))
indexOf will ignore holes. So
[1, 2,, 4, 5].indexOf(undefined)
Always returns -1.
Assuming we have no prior knowledge of operations being performed on the array, the fastest way is to simply iterate through the entire array linearly
var arr = [1, 2, , 4];
for (var i = 0; i < arr.length; i++) {
if (typeof arr[i] === 'undefined') {
arr[i] = 'foo';
break;
}
}
Or we can keep track of whats being removed using something like this
var earliestRemoved;
if (newRemoved < earliestRemoved || !earliestRemoved) {
earliestRemoved = newRemoved;
}
I guess the simplest way would be to use Array.indexOf to find the index of the first undefined element.
Today I've got the same question, so here's my take on it.
It all depends on your specific problem. My problem was this:
I have an array instances[], with objects in it;
Methods of some of these are registered as callbacks elsewhere;
Sometimes I do need to remove some instance from an array;
Sometimes I need to add new instance;
The problem is that I can't just splice an array, because it'll invalidate all my callback registrations. Well, I can just leave them in the array and forget, adding new elements at the end. But it's.... bad. It's leaking memory.
So I came with an idea of making "holes" in an array in place of removed elements, and then re-using these holes for new elements.
Thus the question "how to find undefined elements in an array?".
Someone here suggested using array.indexOf(undefined) - unfortunately that won't work... for some reason.
But, if it's okay in your case to use null or 0 instead, then it will work.
Here's an example:
var A = [1,1,1,1, , ,0,0,null,1,1];
A.indexOf(undefined); // output: -1 (doesn't work)
A.indexOf(0); // output: 6
A.indexOf(null); // output: 8
Hope this'll be useful.
With the hindsight of about 4.3 years behind me, What I'd do now is, since I'm the owner of the array, is to make an object with 2 arrays in it, the 2nd just contains the indexes that are cleared out. (prob. manage it in a class). So always have clear set with knowledge of what's undefined.
This to avoid iterating through arrays linearly.
2021
Nowadays you can safely use:
myArray.findIndex((element) => (typeof element === "undefined"));

Create nested arrays on a loop in Javascript

When I'm working with data, I normally have the need of create Arrays or Objects on a loop, let's say "on the fly".
Lets say for example I want to rearrange an array grouping the element by one of the array keys: One of the methods I use is to loop trough an for in. But the problem is when I define more than one index on the fly.
for(key in array){
newArray[array[key]['gouping_key']] = array[key];
}
This example works fine. But if you have more than one element with the same grouping_key, this code is going to override your previous element.
So, I try this:
var i = 0;
for(key in array){
newArray[array[key]['gouping_key']][i] = array[key];
i++
}
But when I add that second index the interpreter complains saying that the newArray[array[key]['gouping_key']] is undefined. Problem it doesn´t seems to have on the previous example.
Why is that?
I've made this fiddle with an example in case the previous snippets an explanation would be insuficient and unclear. In the fiddle you have three snippets (two commented out).
The first one is the error I get when trying something like what Iǘe mentioned previously.
The second is the solution I use.
And the third an example of the creation of an array on the fly with only one index.
Summing up, I want to know why, when you add the second index, you get that error.
Thanks!
var i = 0;
for(key in array){
// If nested object doesn't exist, make an empty one.
newArray[array[key]['gouping_key']][i] =
newArray[array[key]['gouping_key']][i] || [];
newArray[array[key]['gouping_key']][i] = array[key];
i++
}
You need to create an array to push to, it's not created for you. You can use the || operator to only create an empty array if it's undefined.
Also, that's a lot of nesting to follow... If I may...
var x, y;
y = 0;
for(key in array){
x = array[key].gouping_key;
newArray[x][y] = newArray[x][y] || []
newArray[x][y] = array[key];
y++
}
See how much more readable that is? It's also faster! You dont have to deeply traverse complex objects over and over again.
First using for in for arrays is no good idea, it does not what you are expecting I think. see: https://stackoverflow.com/a/4261096/1924298. Using a simple for loop (or while) should solve your problem.

Array type being picked up as array value

I have some simple Javascript looping through an array of items (Tridion User Groups) to check if the user is a member of a specific group.
I can easily code around the issue shown below ( see && extensionGroup !== 'true') but I want to understand why the isArray = true is counted as a value in the array - any ideas?
The screenshot below demonstrates that the value extensionGroups has been set thus
var extensionGroups = ["NotEvenARealGroup", "Author", "ExampleGroupAfterOneUserIsActuallyIn"];
but returns the isArray value as a 4th value?
updated to show images a little clearer
You're using for in to iterate an array; don't do that. Use for (or forEach):
for(var i = 0; i < extensionGroups.length; i++) {
var extensionGroup = extensionGroups[i];
// ...
}
The reason this fails is because for in is used to iterate over an object's properties in JavaScript. Iterating over an array in this way means you get anything else assigned to it, such as this property or length.
And if you're able to use Array#forEach, it's probably most appropriate here:
extensionGroups.forEach(function(extensionGroup) {
// ...
});
For..in, technically speaking, doesn't iterate through values. It iterates through property names. In an array, the values ARE properties, under the hood. So when you iterate over them with for..in you get funky stuff like that happening.
Which highlights my next point: don't use for..in. Don't use it for arrays -- don't use it for anything, really. Ok -- maybe that's going a bit too far. How about this: if you feel the need to use for..in, think hard to see if it's justifiable before you do it.

Categories