This question already has answers here:
Strange behavior of an array filled by Array.prototype.fill()
(9 answers)
Closed 3 years ago.
I am trying to create an array which has a defined length and fill it with empty arrays. I've tried using all possibilities given by #stpoa's answer here but my array does not behave correctly.
Given the code (I simplified it for the sake of example):
const tasksArray = Array(3).fill([])
const tasksArray2 = [[], [], []]
const tasks = ['task1', 'task2']
const fillWithData = (array) => {
tasks.forEach(task => {
array[0].push(task)
})
}
Gives me an incorrect output for tasksArray and a obviously a correct one for tasksArray2 which is hardcoded
fillWithData(tasksArray) // [['task1', 'task2'], ['task1', 'task2'], ['task1', 'task2']] => not OK, duplicates values!
fillWithData(tasksArray2) // [['task1', 'task2'], [], []] => that's OK
In taskArray, the [] you are using is passed as a reference, and the elements in taskArray all reference the same array.
In taskArray2, you have three separate empty arrays, [], each with their own reference. Therefore you do not get duplicated values.
If you wish to create an array of empty arrays programmatically, use Array.from -
const fillEmptyArrays = (count) =>
Array.from(Array(count), _ => [])
const tasks =
fillEmptyArrays(3)
console.log(tasks)
// [ [], [], [] ]
And please don't include type names like Array in your variable names tasksArray; just name it tasks. JavaScript is a dynamically-typed language and this kind of thinking hurts you in the long run.
You need to get independent object references inside of the array, instead of having literally the constant value.
By taking Array.from with an object with a length property and the build in mapping function, you could get an array of independent arrays.
const tasksArray = Array.from({ length: 3 }, _ => [])
const tasks = ['task1', 'task2']
const fillWithData = (array) => {
tasks.forEach(task => {
array[0].push(task)
})
};
fillWithData(tasksArray);
console.log(tasksArray);
fill puts the value you pass it at each index of the array.
So tasksArray has three references to the same array, while tasksArray2 has a reference to each of three different arrays.
If you want to put three different arrays in there, then you need to explicitly create three arrays.
You could approach it with a counter:
const tasksArray2 = [];
let count = 3;
while (count--) {
tasksArray2.push([]);
}
Related
This question already has answers here:
Group array items using object
(19 answers)
How can I group an array of objects by key?
(32 answers)
Closed last month.
I am trying to create a new array of objects by comparing two arrays.One array contains the ids to be compared and the other contains the dataset which should be compared with the first array are a new array of object must be created.
Let me explain this in detail
Consider array 1:
['1','2']
Array 2
[{name:'Linus',id:'1'},{name:'Anthony',id:'1'},{name:'Jake',id:'2'},{name:'Eva',id:'2'}]
What I am expecting as a output is:
[
{id:'1',users:[{name:'Linus',id:'1'},{name:'Anthony',id:'1'}]},
{id:'2',users:[{name:'Jake',id:'2'},{name:'Eva',id:'2'}
]
I am not sure what has to be done.
Something like this for example
const ids = ['1','2'];
const users = [{name:Linus,id:'1'},{name:Anthony,id:'1'},{name:Jake,id:'2'},{name:Eva,id:'2'}];
const groups = ids.map(id =>{
return {
id,
users: users.filter(u => u.id === id)
}
})
const groupBy = ['1','2'];
const data = [{name:'Linus',id:'1'},{name:'Anthony',id:'1'},{name:'Jake',id:'2'},{name:'Eva',id:'2'}];
const result = groupBy.map(id => {
return {
id,
users: data.filter(item => item.id == id),
}
})
console.log(result);
Try this code
I am creating a filter for a diagram. Whenever a filter is clicked it should remove that category from the diagram. The api call returns an object with names. let’s say the object returns 40 items and I want to filter 5 out by name. What is the best way to approach this?.
I tried to manually type the property names into an array and run the .filter on my object like below. However it returns the entire object unfiltered.
filterDiagram() {
Const array = [“all the names of the properties I want to filter out”]
carbonates = array.forEach(x) => {console.log(x)}
Const filterCat = data.filter (io =>
io.name !== carbonates)
}
Let's say, the array consists of all the names/categories you want to take out.
const toBetakenOut = ['fruits','salts', 'etc' ]
// Please make sure they are not 1 string but rather comma-separated values.
You can filter the API data by using the filter function on the data,to remove objects with names that are within toBetakenOut.
const filterCat = data.filter (io => !toBetakenOut.includes(io.name))
function filterDiagram(){
const dontWantsArray = [/*all of the things you dont want*/];
// Outputs an array of keys
const filteredKeys = Object.keys(yourJSObject)
.filter(key => !dontWantsArray.includes(key));
// After you found the keys you can get the values to another array by keys
const filteredValues = filteredKeys.map(key => yourJSObject[key]);
}
This question already has an answer here:
javascript push returning number instead of object [duplicate]
(1 answer)
Closed 8 months ago.
I am experiencing unexpected behaviour of push function.
The problem is with the latest line of code cited below.
export enum non_searchFieldsNames {
language = 'language',
categories = 'categories',
subtitle = 'subtitle',
publishedDate = 'publishedDate',
id = 'id',
}
enum columnsEnum {
title,
authors,
language,
categories,
subtitle,
publishedDate,
}
function toArray(obj: header | contentCategories | sourceFields) {
return Object.entries(obj)
.sort((a, b) => {
return +a - +b;
})
.map(item => item[1]);
}
let sourceFieldsObject: sourceFields = {
[columnsEnum.title]: searchFieldsNames.title,
[columnsEnum.authors]: searchFieldsNames.authors,
[columnsEnum.language]: non_searchFieldsNames.language,
[columnsEnum.categories]: non_searchFieldsNames.categories,
[columnsEnum.subtitle]: non_searchFieldsNames.subtitle,
[columnsEnum.publishedDate]: non_searchFieldsNames.publishedDate,
};
const sourceFieldsArray = toArray(sourceFieldsObject).push(non_searchFieldsNames.id);
The problem is with the latest line of code. The value I do receive here is 7.
When I simplify it like this
const sourceFieldsArray = toArray(sourceFieldsObject)
I receive an array(however, without the value I try to add, of course).
When I split the logic
const sourceFieldsArray = (toArray(sourceFieldsObject));
sourceFieldsArray.push(non_searchFieldsNames.id);
I get what I wanted. Anyway, I would like to have it as one-liner. So, what is my error?
I have tried also
const sourceFieldsArray (toArray(sourceFieldsObject)).push(non_searchFieldsNames.id)
But it does not help.
push modifies the main array directly, and it does not return a new array as you expected, but the count of items in that array.
You can check the below demo for push's returned value
const array = [1,1,1] //3 items
const count = array.push(1) //1 more item
console.log(count) //total is 4 items
If you want to have a one-liner, you can try the cloning approach with the spreading operator
const sourceFieldsArray = [...toArray(sourceFieldsObject), non_searchFieldsNames.id]
Side note that this approach means you're creating a new array completely, so you need to be aware of some performance situations with a huge array.
This question already has answers here:
Get all unique values in a JavaScript array (remove duplicates)
(91 answers)
Closed 1 year ago.
I have this array of objects, my aim is to remove dublicate values from values array, I want the result to be [{name:'test1', values:['35,5', '35,2','35,3']}, {name:'test2', values:['33,2', '34,3', '32,5']}]
I have tried following solution but it does not works, Do you have any suggestions? Thanks in advance
let arr = [{name:'test1', values:['35,5', '35,2', '35,2', '35,3', '35,5']},
{name:'test2', values:['35,1', '35,1', '33,2', '34,3', '32,5']}]
let uniqueArray = arr.values.filter(function(item, pos) {
return arr.values.indexOf(item.values) == pos;
})
console.log(uniqueArray)
}
}
You can easily remove duplicates from an Array by creating a new Set based off it.
Set objects are collections of values. You can iterate through the elements of a set in insertion order. A value in the Set may only occur once; it is unique in the Set's collection
If you want the result in an array, just use spread syntax for that, for example:
let arr = [{
name: 'test1',
values: ['35,5', '35,2', '35,2', '35,3', '35,5']
},
{
name: 'test2',
values: ['35,1', '35,1', '33,2', '34,3', '32,5']
}
];
const uniqueArr = arr.reduce((accum, el) => {
// Copy all the original object properties to a new object
const obj = {
...el
};
// Remove the duplicates from values by creating a Set structure
// and then spread that back into an empty array
obj.values = [...new Set(obj.values)];
accum.push(obj);
return accum;
}, []);
uniqueArr.forEach(el => console.dir(el));
This question already has answers here:
How can I create a two dimensional array in JavaScript?
(56 answers)
Closed 5 years ago.
const array = new Array(9).fill([]).forEach(function(value, index, arr) {
arr[index] = Array(9).fill(0);
console.log(index, arr[index]); // This line report properly by creating
}); // new array.
console.log(array); // Reported as underdefined.
However, if redefine as below, it works as expected.
const array = new Array(9).fill([]);
array.forEach( function(value,index,arr){
arr[index] = Array(9).fill(0);
console.log(index,arr[index]);
});
console.log(array);
I would like to define multiple dimensional arrays within one line used as this state command.
But what is the problem for scenario 1 where bounded forEach methods array definitions work fine?
But what is the problem for scenario 1 where bounded forEach methods
array defnitions works fine.
Problem is forEach returns undefined
I woule like to define multiple dimensional arrays within one line
used as this.state command.
You can use map for the same
var output = new Array(9).fill([]).map( function(value,index,arr){
return Array(9).fill(0); //return the inner array
});
Or as #bergi suggested, you can use Array.from as well
var output = Array.from(Array(9)).map( function(value,index,arr){
return Array(9).fill(0);
});
As other answers have already mentioned Array.forEach returns undefined or does not return anything, you cannot use it.
As an alternate approach, you can use Array.from.
Following is a sample:
var output = Array.from({
length: 9
}, () => {
return Array.from({
length: 9
}, () => 0)
});
console.log(output)
Also, one more issue with your code is, you are using an object in Array.fill. What array.fill does is, it will create the value to be filled first and then fill it in all items.
var output = new Array(9).fill([]);
output[0].push(1);
console.log(output)
In you check the output, it says /**ref:2**/, but if you check in console, you will notice that all items will have item 1. So you should avoid using objects with Array.fill.
You want to generate array of 9 arrays filled with 0 and return it to variable.
You can achieve this using map method.
const array =
new Array(9)
.fill([])
.map(function(){
return Array(9).fill(0);
});
console.log(array);
p.s. no value, index and etc needed to pass to map methods argument in Your case
Array.prototype.forEach returns undefined. Just call the forEach like below.
const array = new Array(9).fill([])
array.forEach( function(value,index,arr){
arr[index] = Array(9).fill(0);
});
// [
// [0, 0, 0, ...],
// ...
// ]
Using map would be another choice, but I don't vote for it because it creates yet another array in memory.