I am using this handy function:
function not(a, b) {
return a.filter((value) => b.indexOf(value) === -1);
}
Then I have this
let AvailableList = not(FullList, MyList);
If I were to give example of first element in MyList and FullList it is:
appName: "MyAppName*"
description: null
permissionID: MyAppID*
permissionName: "MyAppPermName*"
__proto__: Object
So initially AvailableList is full of items like above. When user makes selection and saves it I save it into MyList. So then I need to use this not function to calculate remaining parts from MyList. But even when I move the first item of AvailableList to MyList then check like if(AvailableList === MyList) console.log(true) else console.log(false) I get false. But if I console log both of the array's first items they print identical values. I tried to compare after declaring variables using Object.assign() as well but no help.
Perhaps I can tackle this easily checking a value like permissionID, but I do not want to go that route since there will be other items later on that won't have permissionID.
If you know of a different function that can do a better job, feel free to share. Please don't share library solutions like Lodash.
*entries are masked
Related
I have the following code which feels a bit redundant as I'm iterating over the same array many times, any suggestions to improve while keeping it readable would be appreciated.
The array object format is a standard one where I am checking the keys in each object to check it matches a certain condition e.g. every object contains one value, or only some of them do e.t.c [{},{},{}]
const getValue = arrayOfObjects => {
const hasA = arrayOfObjects.some(
object => arrayOfObjects.abc === 'val1'
);
const hasB = arrayOfObjects.every(
object => arrayOfObjects.abc === 'val2'
);
// the above 2 iterations are repeated about 4 more times for different checks
// then there are a few versions of the below assignment depending on the above variables
const hasC =
hasA ||
hasB;
// finally the function returns one of the values
if (hasA) {
return 'val10';
} else if (hasB) {
return 'val11';
} else if (hasD) {
return 'val12';
}
};
This sounds like a theoretical question. It sounds like you're wondering if using a few Array.prototype methods like some and every on the same array over and over has downsides or if there is a more readable way to do it.
It depends.
If the size of the array n is generally pretty small, in a practical sense, it doesn't matter. Choose what is more readable. Big O complexity comes more into play on a practical level if you're dealing with a lot of array items.
Boolean vars derived from some and every can be very readable in my opinion.
If you are in a situation where the array could be quite large, you could consider trying to do it in one step. Array.prototype.reduce would be a good tool for this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
In general when you're making use of every and some (which I personally love, as they're very readable), you should stop and think about the necessity of the checks you're making.
To simplify the examples you had, let's say you have a bunch of fruits and you're checking whether:
There is at least one orange.
All of the fruits are apples.
It's clear that
If (1) is true, then (2) must be false
And the other way around:
If (2) is true, then (1) must be false
Then you can spare the testing one of them if the other one is true, using else if for example.
Additionally, if one of them is false - then you simply don't have to check (1) or (2), which is guaranteed to be false.
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.
In an answer, #Tushar suggested the syntax corresponding to the following.
Array.apply(null, Array(3).fill(10))
.map(function (item, index) {
return item + index;
});
I do understand what's going on here and I'm satisfied. However, it bugs me a bit that there's this null valued argument doing seemingly nothing. So I went off and started researching. According to the wisdom on the web, it's a reference to this. Now, that gave me very little clarity and despite of putting in cucumbers, arrays, and objects into that, it didn't affect jack, as far I could tell. In fact, I'm curious why the following wouldn't be equivalent, let alone suffice.
Array(3).fill(10)
.map(function (item, index) {
return item + index;
});
Further on, I read something about Cr an IE not accepting array-like objects, which tells me even less. Also, it's a bit hard to verify the age of the article so the validity of its claim's hard to assess. I got as far as to the talk about prototype constructors and gave up, not being sure if I'm on the right path.
The first argument of apply is only important if you're using a function that uses this.
Running the following snippet should make it a little clearer:
var o = {value: 1};
var fn = function(a) {
console.log(a + this.value);
}
value = "something else";
fn("an argument ");
fn.apply(o, [20]);
// the above prints:
// an argument something else
// 21
https://jsfiddle.net/f2zw8edd/
Array(number) creates an array of the given size, however it does not populate any of its data points. Calling map or fill or pretty much anything else on it therefore won't do anything useful.
Array(item1, item2, item...) on the other hand creates an array with the given items as elements of the array. You can call map, fill, whatever you want on this and it will work.
So how can you use this to create an array of a given size that you can call map on? Exactly the way you see.
What Array.apply(null,Array(3)) does is create an unpopulated array of size 3, then passes those 3 undefined items as arguments to Array, thus resulting in
Array(undefined,undefined,undefined), which gives you a mappable array. It's important to note that you're creating two arrays here, but the Array(3) is discarded after use.
So why null? That would be because when creating an array, there is no place where this is relevant. Since the context is irrelevant, you can pass literally anything you want as the context and it will run just fine, but it's easiest to understand that context doesn't matter if you pass it null.
I am reading through Eloquent JavaScript and have been stuck trying to understand lists for about two days so I figured I would finally ask a question. The example they give in the book is:
var list = {
value: 1,
rest: {
value: 2,
rest: {
value: 3,
rest: null
}
}
};
Now I think I understand the example... There is a list object and it has properties value and rest. Then, rest has properties of value and rest, etc... However, I don't understand what rest is or even stands for. Does the rest property contain an object? So, list.rest.value would == 2? How is this useful? Some ways I could see this as useful are having a list Car, with prop engine, gauge, etc, with further properties of accelerate, brake, low fuel... How would something like this be achieved?
I do apologize for the "all overness" of this post, I don't exactly know what to ask or how to phrase it. It seems like the book only explained objects and properties, but never actually having objects as an objects property.
Thank you all in advance, and if you need any clarification or more info I will try to provide it.
This code simply uses JavaScript Object Notion to define an object named list.
// Would simply define an empty object.
var list = {};
Now you can add some properties to the object.
// Would define an object with a single property: `value`.
var list = {
value: 1
};
Using nested object declarations, you can give the list object child objects as well:
var list = {
value: 1,
rest: {}
};
Now list.rest is an empty object. You can fill that out by adding some properties:
var list = {
value: 1,
rest: {
value: 2
}
};
And your nesting can continue ad-infinitum. The object in your original post, the following is possible:
console.log(list.value); // 1
console.log(list.rest.value); // 2
console.log(list.rest.rest.value); // 3
It's important to understand that this in no way creates a class or includes any additional methods with the object. It seems to be structured as a linked list but provides no functionality to add/remove/modify (except by directly modifying the original object).
In the example above the list variable is an associative array. This is JavaScript's version of an "object". While the property list.value ends up being typed as an integer, the property list.rest is typed as a nested associative array. The properties themselves can be any valid type. Many jQuery plugins are coded where the properties themselves are actually delegate functions.
The object you have described above in the example does not seem to me to be terribly useful beyond being an example of how this kind of object can contain references to other objects. However, when you begin applying this in an "object oriented" concept (keep in mind that it is not truly object oriented), it becomes more useful. You can then create your own "namespace" with properties, functions and delegates that can be re-used time and again.
Thank you all for your information. I don't know if there is a best answer selection on this site or not, but I really do appreciate the help Justin, Joel, and Evan. I think the main part I was confused about is just practical application for real applications. I have messed around a little bit and came up with this and have a much better basic understanding now:
var car = {
engine: {
turn_on: "Turned engine on",
turn_off: "Turned engine off",
desc: {
size: "V6",
year: 2000
}
},
fuel: {
level: 55
}
};
function CheckFuel(fuel){
if(fuel > 50){
console.log("In good shape");
}
else{
console.log("We should fuel up");
}
}
console.log(car.engine.turn_on);
console.log(car.engine.turn_off);
console.log(car.engine.desc.size);
console.log(car.engine.desc.year);
CheckFuel(car.fuel.level);
Now time to practice iterating through. Thanks again!
This is an implementation of a linked list. Each node in the list has a reference to the next node. 'Rest' is an object (the next node in the list) that also contains every other node in the list (via it's rest property).
The first value in the list would be list.value;. The second value in the list would be list.rest.value;. The items in the list can be shown as:
item1 = list;
item2 = list.rest;
item3 = item2.rest;
This continues until itemX.rest is null.
These two functions could be used to manage the list and may help you understand how iterating through it would work:
function addToList(item)
{
if(!list)
{
list = item;
return;
}
var temp = list;
while(temp.rest)
{
temp = temp.rest;
}
temp.rest = item;
}
function printList()
{
var temp = list;
while (temp)
{
print temp.value; //i'm not sure what the javascript print function is
temp = temp.rest
}
}
The add function would be called like this: addToList({ value:10, rest:null });
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.