push method not returning new array - javascript

I am adding an object to an array through javascript push() method. My array is an array of objects. I want to console.log() the new array. But it is giving me the length of new array. I know push() method returns the length of new array but I want to use the new array in my application. How to get it
let sub_sprite = this.state.sub_sprite;
let updated_sub_subsprite;
updated_sub_subsprite = sub_sprite.push(this.state.sprite[that.state.sprite_count]);
console.log(updated_sub_subsprite);
that.setState({sub_sprite:updated_sub_subsprite}, ()=>{
console.log(this.state.sub_sprite)
});

Do not use Array.push on an array stored in your React component's state, it will mutate the state directly, which may lead to problems (see this article).
You can use Array.concat to create a new array with the additional value:
let sub_sprite = this.state.sub_sprite
let updated_sub_subsprite;
updated_sub_subsprite = sub_sprite.concat([this.state.sprite[that.state.sprite_count]]);
console.log(updated_sub_subsprite);
that.setState({sub_sprite:updated_sub_subsprite}, ()=> {
console.log(this.state.sub_sprite)
})
A more consise and convenient way is using the spread syntax (notice the three dots):
let sub_sprite = this.state.sub_sprite
let updated_sub_subsprite;
updated_sub_subsprite = [...sub_sprite, this.state.sprite[that.state.sprite_count]);
console.log(updated_sub_subsprite);
that.setState({sub_sprite:updated_sub_subsprite}, ()=> {
console.log(this.state.sub_sprite)
})

The Array#push method does not return a new array, but rather the length of the array after the item(s) have been added to that array instance.
It looks like the Array#concat method would be a better fit for what you're trying to do, seeing that offers the "appending behavior" and also returns the resulting array.
Consider making the following adjustments to your code, making use of concat() to achieve what you want:
let sub_sprite = this.state.sub_sprite;
// Create a new array via concat(), adding a new array with one item
// that is [ sub_sprite [that.state.sprite_count] ] to sub_sprite
let updated_sub_subsprite = sub_sprite.concat( [ sub_sprite [that.state.sprite_count] ]);
console.log(updated_sub_subsprite);
that.setState({sub_sprite : updated_sub_subsprite }, ()=>{
console.log(this.state.sub_sprite)
})

Related

How do the map function that return an object with modified keys? (JS, React.js)

I am trying to create an object with modified keys after map() function (the data is from API), here is my code:
const getData = mySchedule.schedules.map((data) => ({
[data.id]: false,
}));
setCheckId(getData);
This code return:
And I want this output:
Do you have any solution for this case? thank you.
Solution:
Create an object => const getData = {};
Iterate => mySchedule.schedules
Set id as a key and false as value => getData[item.id] = false;
const getData = {};
mySchedule.schedules.forEach(item => {
getData[item.id] = false;
});
setCheckId(getData);
The above answer is correct, but let's dive deep into the problem first:
The map function returns an Array, what you want is an Object. The map function applies the callback for every element and returns a new array of elements modified by the callback function. What are you seeing is the array returned by the map function, note that 1,2,3,4is the index position of the array. Read more about the function map here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
The output that you want is an object, but as we have learned before the map function always returns an array with new elements resulting from your map function callback.
If you want an object that are many ways to achieve that, you can loop through the array and add properties to the object.
If you want to understand more and dive into array methods, you can even achieve that using reduce method, therefore the first answer is simpler:
/* Another example using reducer */
const data = [ {10:false,20:false}];
const reducer = (accumulator, currentValue) => currentValue[accumulator] = false;
setCheckId(data.reduce(reducer));

can I use forEach to make every element of an array a new object?

I created an array with many elements with a loop:
myArray = [c1, c2, c3...]
now I want to make each element into an object and assign different key values:
c1 = {image = path, value = number)
I tried to run forEach() but can't figure out the correct way to do so and I have not succeeded in finding the answer to it.
My guess was:
myArray.forEach(function() {
let name = {
image = path,
value = number,
}
return name;
});
but there's no change in the elements in the log.
Any help or link to an answer that can help me here. First time coding here.
UPDATE: an easier solution was to .push all the keys and values of the objects when I created the array with the loop in the first place.
array.push({image: pathx, value: numberx})
You can, but you'd be better off with a simple for loop:
for (let i = 0; i < myArray.length; ++i) {
let entry = myArray[i];
myArray[i] = {image: entry.path, value: entry.number};
}
Or making a new array with map.
newArray = myArray.map(entry => ({image: entry.path, value: entry.number}));
Or if you prefer non-arrow functions:
newArray = myArray.map(function(entry) {
return {image: entry.path, value: entry.number};
});
You could theoretically push to a new array but this is the exact usecase for Array#map. Array#map maps old values to new values. The returned object from the callback is the new object and the returned array is the new array containing the new objects.
Semantically, Array#forEach is to plainly iterate over each element in an array, and possibly execute something with side-effects (which may include pushing to another array). But with Array#map, it's specifically used to transform old array values to new ones. Use the one that is specifically designed because it conveys a clear message to anyone else who reads your code.
const newArray = myArray.map(({ path, number }) => ({
image: path,
value: number
}));
Array#map maps old values to new values. You may need to use the follwing instead of arrow functions as it is not supported in IE.
I just added dummy data in the object, you can change it.
myArray = ["c1", "c2", "c3"]
myArray = myArray.map(function(elem) {
return {"image":"path"+elem,"value":"value"+elem};
});
console.log(myArray);

Return an Array of Abbreviated Strings with .filter() - JavaScript

If I have an array of strings that I would like to abbreviate with the filter() method.
How would I use filter() in combination with str.substring (or another string method if applicable)?
In the following code I would like to return the first four characters of each name, but it doesn't seem to be working.
JavaScript
let poshNames = ["Markol", "Andile", "Jazzmine", "Famisynth"];
let nickNames;
nickNames = poshNames.filter(function(name){
return name.str.substring(0,4);
});
You should use map:
const poshNames = ["Markol", "Andile", "Jazzmine", "Famisynth", "H"];
const nickNames = poshNames.map(name => name.substring(0,4));
console.log(nickNames);
Use map instead of filter
and it will work:
let poshNames = ["Markol", "Andile", "Jazzmine", "Famisynth"];
let nickNames;
nickNames = poshNames.map(function(name) {
return name.substring(0,4);
});
What filter does is essentially return an array that contains every element in the array for which the function returns true.
What map does, on the other hand, is return an array that contains the value the function returns for every value in the array.
Note: Both methods return a new array without affecting the original.

Is it possible to use array iteration methods on ES6 Set instances?

I am using ES6 Set instances and I need to apply some transformations on them. These are transformations of the kind that would be simple if they were arrays. Here is an example:
let s = new Set;
s.add(1);
s.add(2);
s.add(3);
let n = s.filter(val => val > 1); // TypeError, filter not defined
let n = Array.prototype.filter.call(s, val => val > 1); // []
I was hoping that the result would either be a new Set or an array. I similarly want to use other array comprehension methods like filter, map, reduce, etc. And I would also like to have similar behaviour on ES6 Map instances as well.
Is this possible, or do I need to be using vanilla JS arrays?
you can get the values of s in an array using
Array.from(s.values())
Array.from documentation states that it creates a new Array instance from an array-like or iterable object.
Set.values returns a new Iterator object that contains the values for each element in the Set object in insertion order.
So your code becomes
let s = new Set;
s.add(1);
s.add(2);
s.add(3);
let n = Array.from(s.values()).filter(val => val > 1)
You can't use Array methods directly on a Set or Map object. Array methods expect .length and [n] indexing which is not how Set or Map work.
You can either convert your Set to an array using Array.from(s) or you can create your own methods to operate directly on the Set or Map. If you're going to be doing this a lot and the desired end result is a Set or Map, then it's probably better to not convert to an Array, modify, then convert back. Plus, converting a Map to an array is not quite so simple since you have both a key and value (might have to be an array of objects).
For example, you could create your own .filter() method for a Set object like this:
Set.prototype.filter = function(fn) {
let result = new Set();
for (let val of this) {
if (fn(val, this) === true) {
result.add(val);
}
}
return result;
}
let s = new Set;
s.add(1);
s.add(2);
s.add(3);
let n = s.filter(val => val > 1);
// log the output
// log output
document.write("Set {" + Array.from(n).join(", ") +"}");
Similar methods could be created for other Array methods.

How to convert Set to Array?

Set seems like a nice way to create Arrays with guaranteed unique elements, but it does not expose any good way to get properties, except for generator [Set].values, which is called in an awkward way of mySet.values.next().
This would have been ok, if you could call map and similar functions on Sets. But you cannot do that, as well.
I've tried Array.from, but seems to be converting only array-like (NodeList and TypedArrays ?) objects to Array. Another try: Object.keys does not work for Sets, and Set.prototype does not have similar static method.
So, the question: Is there any convenient inbuilt method for creating an Array with values of a given Set ? (Order of element does not really matter).
if no such option exists, then maybe there is a nice idiomatic one-liner for doing that ? like, using for...of, or similar ?
if no such option exists, then maybe there is a nice idiomatic
one-liner for doing that ? like, using for...of, or similar ?
Indeed, there are several ways to convert a Set to an Array:
Using Array.from:
Note: safer for TypeScript.
const array = Array.from(mySet);
Simply spreading the Set out in an array:
Note: Spreading a Set has issues when compiled with TypeScript (See issue #8856). It's safer to use Array.from above instead.
const array = [...mySet];
The old-fashioned way, iterating and pushing to a new array (Sets do have forEach):
const array = [];
mySet.forEach(v => array.push(v));
Previously, using the non-standard, and now deprecated array comprehension syntax:
const array = [v for (v of mySet)];
via https://speakerdeck.com/anguscroll/es6-uncensored by Angus Croll
It turns out, we can use spread operator:
var myArr = [...mySet];
Or, alternatively, use Array.from:
var myArr = Array.from(mySet);
Assuming you are just using Set temporarily to get unique values in an array and then converting back to an Array, try using this:
_.uniq([])
This relies on using underscore or lo-dash.
Perhaps to late to the party, but you could just do the following:
const set = new Set(['a', 'b']);
const values = set.values();
const array = Array.from(values);
This should work without problems in browsers that have support for ES6 or if you have a shim that correctly polyfills the above functionality.
Edit: Today you can just use what #c69 suggests:
const set = new Set(['a', 'b']);
const array = [...set]; // or Array.from(set)
Use spread Operator to get your desired result
var arrayFromSet = [...set];
The code below creates a set from an array and then, using the ... operator.
var arr=[1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,];
var set=new Set(arr);
let setarr=[...set];
console.log(setarr);
SIMPLEST ANSWER
just spread the set inside []
let mySet = new Set()
mySet.add(1)
mySet.add(5)
mySet.add(5)
let arr = [...mySet ]
Result: [1,5]
In my case the solution was:
var testSet = new Set();
var testArray = [];
testSet.add("1");
testSet.add("2");
testSet.add("2"); // duplicate item
testSet.add("3");
var someFunction = function (value1, value2, setItself) {
testArray.push(value1);
};
testSet.forEach(someFunction);
console.log("testArray: " + testArray);
value1 equals value2 => The value contained in the the current position in the Set. The same value is passed for both arguments
Worked under IE11.
Using Set and converting it to an array is very similar to copying an Array...
So you can use the same methods for copying an array which is very easy in ES6
For example, you can use ...
Imagine you have this Set below:
const a = new Set(["Alireza", "Dezfoolian", "is", "a", "developer"]);
You can simply convert it using:
const b = [...a];
and the result is:
["Alireza", "Dezfoolian", "is", "a", "developer"]
An array and now you can use all methods that you can use for an array...
Other common ways of doing it:
const b = Array.from(a);
or using loops like:
const b = [];
a.forEach(v => b.push(v));
the simplistic way to doing this
const array = [...new Set([1,1,2,3,3,4,5])]
console.log(array)
Here is an easy way to get only unique raw values from array. If you convert the array to Set and after this, do the conversion from Set to array. This conversion works only for raw values, for objects in the array it is not valid. Try it by yourself.
let myObj1 = {
name: "Dany",
age: 35,
address: "str. My street N5"
}
let myObj2 = {
name: "Dany",
age: 35,
address: "str. My street N5"
}
var myArray = [55, 44, 65, myObj1, 44, myObj2, 15, 25, 65, 30];
console.log(myArray);
var mySet = new Set(myArray);
console.log(mySet);
console.log(mySet.size === myArray.length);// !! The size differs because Set has only unique items
let uniqueArray = [...mySet];
console.log(uniqueArray);
// Here you will see your new array have only unique elements with raw
// values. The objects are not filtered as unique values by Set.
// Try it by yourself.
I would prefer to start with removing duplications from an array and then try to sort.
Return the 1st element from new array.
function processData(myArray) {
var s = new Set(myArray);
var arr = [...s];
return arr.sort((a,b) => b-a)[1];
}
console.log(processData([2,3,6,6,5]);
function countUniqueValues(arr) {
return Array.from(new Set(arr)).length
}
console.log(countUniqueValues([1, 2, 3, 4, 4, 4, 7, 7, 12, 12, 13]))

Categories