Inserting an object so the array stays sorted - javascript

I have an enum of different Steps
export enum StepCategory {
START = 0,
POSITION_1 = 1,
TRANSPORT = 2,
RECEIVER = 3,
END = 4,
NO_STEP_MATCH = 5
}
This will later result in an array, where for every Step I have an object. The Problem is I won't load all the information at once, so i can'tdo a simple for-loop and push each item chronogically. I could be that I first load the value for Step 4, so my array would be:
var array = [{"END" , "POSITIVE"}]
Afterwards I would get the Info for Step 2, then I would have:
var array = [{"END", "POSITIVE"}, {"TRANSPORT", "POSITIVE"}]
But this is not sorted.
What should I do? Should I declare an array of 6 undefined values
var array = [undefined, undefined, undefined, undefined, undefined, undefined]
This way I wouldn't need any sorting-algorithm after each Update, and can just push the value at the right position.
Just some small Info: I use AngularJS 1, Typescript and Lodash

In plain Javascript, you could sort it with an object and the assigned values of the key.
var StepCategory = { START: 0, POSITION_1: 1, TRANSPORT: 2, RECEIVER: 3, END: 4, NO_STEP_MATCH: 5 },
array = [["END", "POSITIVE"], ["TRANSPORT", "POSITIVE"]];
array.sort(function (a, b) {
return StepCategory[a[0]] - StepCategory[b[0]];
});
console.log(array)

First of all, this is - as someone mentioned in the comments - not syntactically correct:
var array = [{"END", "POSITIVE"}, {"TRANSPORT", "POSITIVE"}]
I assume that this was just a typo writing this question. Additionally if you actually use the enum in your array as key and just left it out for demonstration purposes, I would expect your array of objects to look something like this:
var array = [{StepCategory.END: "POSITIVE"}, {StepCategory.TRANSPORT: "POSITIVE"}]
In order to sort this with LoDash you could use something like this:
var sortedArray = _.sortBy(array, i => Object.keys(i)[0]);
This sorts your array by the value of the first key of each object which refers to your enum value.

Related

How can I filter an array by its properties?

I have a headless CMC WP that's fetched into my Javascript and stored. I want to filter it by a property(if the property value = to the value I input in html then it should append to the innerHTML) and therefore I tried to loop through it but it does not work.
This is my function:
for (let i in this.filtered) {
for (let y in this.filtered[i].categories) {
//console.log(this.filtered[i].categories[y] + " ");
const results = this.filtered[i].categories[y].filter(post => post == value)
console.log(results);
}
}
It says in the console that this.filtered[i].categories[y].filter is not a function.
this is a part of the array from this.filtered, I want to filter by categories.
This is what it shows when I console.log(this.filtered[i].categories[y]);
Thank you in advance!
It says in the console that this.filtered[i].categories[y].filter is not a function.
The items in the categories array, according to your screenshot, are simple integers. Integers don’t understand/implement any method called filter(). (Put another way: what would you do if I told you to filter the number 7?) Logically, it’s clear that this is not what you intended.
While you’re headed down the right path, I’d recommend you keep it simple: run Array.filter on your outermost array and use the logic in the callback to test whether the categories sub-array contains the value you’re looking for:
var _this = {};
_this.filtered = [{
acf: {},
author: 1,
categories: [18, 2, 3]
},
{
acf: {},
author: 2,
categories: [4, 3, 7, 18]
}
];
const value = 2;
var filteredResults = _this.filtered.filter(cv => cv.categories.includes(value));
console.log(filteredResults);

Difference between fill and fill map

I came across some code which was filling an array of objects like so:
const getObj = () => {
return {a: 1, b: 2, c: 3};
}
const arr = Array(3).fill(null).map(getObj);
console.log(arr);
However, I'm wondering what the main purpose of fill(null).map(getObj) is? It seems redundant as I can simply write the following and get the same resulting array:
const getObj = () => {
return {a: 1, b: 2, c: 3};
}
const arr = Array(3).fill(getObj());
console.log(arr);
So, I'm wondering if these two lines of code do exactly the same thing or if there is something I'm missing?
The resulting arrays (top array first method with fill + map bottom array is only using map):
Array(3).fill(getObj()) will fill your array with references to the same object, Array(3).fill(null).map(getObj) will create object per element. See the example below:
const getObj = () => {
return {a: 1, b: 2, c: 3};
}
const arr = Array(3).fill(null).map(getObj);
arr[0].b=4;
console.log(JSON.stringify(arr));
const arr1 = Array(3).fill(getObj());
arr1[0].b=4;
console.log(JSON.stringify(arr1))
When it comes to Array.fill it is stated in the documentation that:
When fill gets passed an object, it will copy the reference and fill
the array with references to that object.
So using a Array.fill with objects has somewhat limited application unless you really want to have multiple objects pointing to the same reference. In more than few use cases however that would lead to bugs if not understood.
For the 2nd case where you do Array(3).fill(null).map(getObj) this is one of the ways to create a new array based on a given arbitrary size and at the same time fill it with new objects.
The real need for the fill(null) is due to the fact that calling Array(3) would only do one thing. Create a new array and set its length property to 3. That is it!
let arr = Array(3) // returns new array with its "length" property set to 3
console.log(arr) // [empty × 3] <-- browser console
So that array now has only length and bunch of empty elements. You can't do much with it until it actually has values. Therefore the need for fill so that you give it any value and then map through it to set the values you actually want. Using Array.map and calling each iteration your function guarantees you do not have same references. You could have skipped the fill step and done something like this:
const getObj = () => ({a: 1, b: 2, c: 3})
// using array destructuring
let arr = [...Array(3)].map(getObj)
arr[0].a = 3
console.log(arr)
// using Array.from
let arr2 = Array.from(Array(3)).map(getObj)
arr2[0].a = 3
console.log(arr2)
There are somewhat shorter and get you the exact same result of filling the array with specified length with objects and not references to the same object.
The trick here is that both would "fill" the array after it is defined with undefined values instead, after which the map would fill it with the values we want.

Javascript: Creating a Dictionary/Map/Object with Sets as keys

Is there any sensible way to make a dictionary in Javascript where the keys are Set objects?
For context, my problem is that I have a list of lists and want to count the number of times each combination occurs, ignoring the order and repetition of elements. I can make a dictionary where the lists themselves are elements, but if I try the same with a set, it treats every set as the same key with value: [object Set].
As an example:
var list_of_lists = [[1,2], [1], [1], [2,1], [1,1]]
var count_of_id_combos = {}
var count_of_id_combo_sets = {}
list_of_lists.forEach(
function(sub_list, index){
count_of_id_combos[sub_list] = (count_of_id_combos[sub_list] || 0) + 1
var set_of_sublist = new Set(sub_list)
count_of_id_combo_sets[set_of_sublist] = (count_of_id_combo_sets[set_of_sublist] || 0) + 1
}
)
console.log(count_of_id_combos) // -> Object {1: 2, 1,2: 1, 2,1: 1, 1,1: 1}
console.log(count_of_id_combo_sets) // -> Object {[object Set]: 5}
whereas I'd like the second object to be something like
Object {1: 3, 1,2: 2}
I've tried using Map as well and the same thing happens. The only solution I've come up with is manually filtering out duplicates and then sorting the lists, which works but seems overly complicated and I wondered if there was something I was missing.
One way to do what you want is to convert a set to a string; for example,
let map = new Map()
let setSet = new Set([3, 1, 2])
let setKey = Array.from(setSet).sort().join()
map.set(setKey, "foo")
let getSet = new Set([2, 1, 1, 3])
let getKey = Array.from(getSet).sort().join()
console.log(map.get(getKey))

how does destructuring array get length property

I came across this destructuring expression in an article.
const words = ['oops', 'gasp', 'shout', 'sun'];
let { length } = words;
console.log(length); // 4
How does length get the value of 4? I know .length is a property of the array, but how does this syntax work? It seems to be doing let length = words.length; and in fact in babel does output it as such. But my question is what is the logic behind it?
What is confusing me is the mix of an array of values and the the use of {length}.
I have read MDN 's description but can't see this example explained.
Intro
I had the same question so I read the docs and it finally clicked for me that the variable (length) is just being assigned the Object’s value at the key with the same name as the variable (words[length]).
That may not make sense, so I’m going to start by explaining this type of destructuring in 2 steps and then show how it applies in this situation.
I’ll then provide one last (cool) example which confused me initially and led me to research this topic. It’s also the exact problem described in a duplicate question.
Destructuring
This syntax is called Object Destructuring (MDN):
let a, b;
({a, b} = {a: 1, b: 2});
a; // 1
b; // 2
({b, a} = {c: 3, b: 2, d: 4, a: 1});
a; // 1
b; // 2
Same result – order doesn't matter!
The variables on the left (a & b) are assigned to the value of their corresponding key's value on the Object (right).
const obj = {a: 1, b: 2};
let {a, b} = obj;
a; // 1
b; // 2
We can store the object on the right into a variable (obj in this case) and then use the same syntax (without parens).
Applied to your Example (Array)
Finally, let's show the words array as an Object (arrays are just Objects under the hood).
Here's what you'll see if you type ['oops', 'gasp', 'shout', 'sun'] into Chrome's console:
const words = {0: 'oops', 1: 'gasp', 2: 'shout', 3: 'sun', length: 4};
let { length } = words;
console.log(length); // 4
Just like above, it's going to set the length variable (left) to the value of the corresponding key in the words Object/array (right). words[length] has a value of 4 so the length variable (left) now has a value of 4 as well.
Example Where Destructuring is Useful
From Wes Bos's Blog:
Given a person Object, how do you create global variables referring to its properties?
const person = {
first: 'Wes',
last: 'Bos',
country: 'Canada',
city: 'Hamilton',
twitter: '#wesbos'
};
Old School:
const first = person.first;
const last = person.last;
The power of destructuring!
const { first, last } = person;
BONUS: Cool Usage w/ Arrow Functions (MDN)
Challenge: return new array with the lengths of the respective elements in the input array.
This example is shown as a way to use arrow functions. All three solutions solve the problem, they’re just showing the evolution to finally arrive at a simple one-liner.
var materials = [
'Hydrogen',
'Helium',
'Lithium',
'Beryllium'
];
materials.map(function(material) {
return material.length;
}); // [8, 6, 7, 9]
materials.map((material) => {
return material.length;
}); // [8, 6, 7, 9]
materials.map(({length}) => length); // [8, 6, 7, 9]
On each iteration of the input array passed to map, we are setting the {length} parameter to the current element of materials that is passed in as an argument:
{length} = 'Hydrogen';
This sets the length variable to the length property of the current string element (more on that below) and then simply returns the value of length to the map function which eventually returns a new array with all of the elements from the original array's lengths as its elements.
Supplement: String (primitive) vs. Array (Object)
"strings" are "primitives", not objects, so they don't have properties BUT when you try to call a property such as .length on a string, the primitive is coerced (changed) into a String Object.
Here's what a String Object looks like in the Chrome console. Notice how it's practically the same as the Array Object. String (function) is a constructor, so calling new will create a new Object constructed from that function with String (Object) as its prototype (which is what __proto__ refers to):
Think of the code as being
const words = {0:'oops', 1:'gasp', 2:'shout', 3:'sun', length:4};
let { length } = words;
console.log(length);
Which it essentially is (nevermind all the other stuff arrays come with)
Does it make sense now?
If you add a property inside the { and } that belongs to the Array, it's value is copied.
Here we check for the property constructor. Will log constructor function to console.
IF you add a property not belongs to an array, will return undefined
Another Example
const words = ['oops', 'gasp', 'shout', 'sun'];
let { constructor } = words;
console.log(constructor);
We are testing for something will return undefined
const words = ['oops', 'gasp', 'shout', 'sun'];
let { something } = words;
console.log(something);

How to get value at a specific index of array In JavaScript?

I have an array and simply want to get the element at index 1.
var myValues = new Array();
var valueAtIndex1 = myValues.getValue(1); // (something like this)
How can I get the value at the 1st index of my array in JavaScript?
You can access an element at a specific index using the bracket notation accessor.
var valueAtIndex1 = myValues[1];
On newer browsers/JavaScript engines (see browser compatibility here), you can also use the .at() method on arrays.
var valueAtIndex1 = myValues.at(1);
On positive indexes, both methods work the same (the first one being more common). Array.prototype.at() however allows you to access elements starting from the end of the array by passing a negative number. Passing -1 will give the last element of the array, passing -2 the second last, etc.
See more details at the MDN documentation.
Array indexes in JavaScript start at zero for the first item, so try this:
var firstArrayItem = myValues[0]
Of course, if you actually want the second item in the array at index 1, then it's myValues[1].
See Accessing array elements for more info.
You can just use []:
var valueAtIndex1 = myValues[1];
indexer (array[index]) is the most frequent use. An alternative is at array method:
const cart = ['apple', 'banana', 'pear'];
cart.at(0) // 'apple'
cart.at(2) // 'pear'
If you come from another programming language, maybe it looks more familiar.
shift can be used in places where you want to get the first element (index=0) of an array and chain with other array methods.
example:
const comps = [{}, {}, {}]
const specComp = comps
.map(fn1)
.filter(fn2)
.shift()
Remember shift mutates the array, which is very different from accessing via an indexer.
Update 2022
With ES2022 you can use Array.prototype.at():
const myValues = [1, 2, 3]
myValues.at(1) // 2
at() also supports negative index, which returns an element from the end of the array:
const myValues = [1, 2, 3]
myValues.at(-1) // 3
myValues.at(-2) // 2
Read more:
MDN, JavascriptTutorial, Specifications
You can use [];
var indexValue = Index[1];
As you specifically want to get the element at index 1. You can also achieve this by using Array destructuring from ES6.
const arr = [1, 2, 3, 4];
const [zeroIndex, firstIndex, ...remaining] = arr;
console.log(firstIndex); // 2
Or, As per ES2022. You can also use Array.at()
const arr = [1, 2, 3, 4];
console.log(arr.at(1)); // 2

Categories

Resources