Correct way to use destructuring in JavaScript - javascript

I get data from the database of which I only need two arrays. Using two variables, I get the result I need, but I understand, that this code is not written correctly. Even npm writes that the arrow function should return something, so I added "return false";
let flagUrls = [];
let countryNames = [];
country.map((country, index) => {
flagUrls[index] = country.flagUrls;
countryNames[index] = country.countryNames;
return false;
});
this.setState({ flagUrls, countryNames });
I tried like this:
let flagsAndCountrys = country.map((country, index) =>[country.flagUrls, country.countryNames])
this.setState({
flagsAndCountrys.flagUrls,
flagsAndCountrys.countryNames
});

mapmethod creates a new array with the return value of the provided function on every element in the calling array.
Notice the word return in the above line. You need to return something that will be inserted in the new array.
So, using map you can create a new array, consisting of objects with only the flagUrls and countryNames field like so:
let result = country.map((country, index) => {
return {
flagUrl: country.flagUrls,
countryName: country.countryNames
}
});
If you want maintain two array of flagUrls and countryNames, you should not be using map. It's better to use forEach here, like so:
let flagUrls = [];
let countryNames = [];
country.forEach((country, index) => {
flagUrls.push(country.flagUrls);
countryNames.push(country.countryNames);
});
Using destructuring for this, replace the first parameter passed to the provided function country with the values like: {flagUrls, countryNames}
country.forEach(({flagUrls, countryNames}, index) => {
flagUrls.push(flagUrls);
countryNames.push(countryNames);
});

The proper way to create two arrays would be to call map twice:
const flagUrls = countries.map(country => country.flagUrl);
const countryNames = countries.map(country => country.countryName);
If you want to do it with only a single iteration, then you'll have to use a loop with side effects - similar to the map call you did, but you'd rather use forEach:
let flagUrls = [];
let countryNames = [];
countries.forEach((country, index) => {
flagUrls[index] = country.flagUrl;
countryNames[index] = country.countryName;
});
or just
let flagUrls = [];
let countryNames = [];
for (const country of countries) {
flagUrls.push(country.flagUrl);
countryNames.push(country.countryName);
}

Related

Insert element inside array

I have a function
checkName(output) {
output.filter((NewData) => {
return this.props.elements.filter((OldData) => {
if (NewData.key == OldData.key) {
NewData.name = OldData.name,
//there i need to add another element
// Need to add newData.number = OldData.number
}
return NewData
})
})
return output
}
and I call this function like:
const named = this.checkName(product.rows)
Now I need to add to my product's array that I passed to checkName the value "OldData.Number" to "newData.Number" that is not defined in product (so I need to create this field)
For example:
Product before the checkName function
product.rows = [NewData.name]
Product after the checkName function
product.rows = [NewData.name="value of OldData.name", NewData.number="value of OldData.number"]
How can I obtain this result?
There are 2 confusing things in your code:
You are using filter to execute an action in each member of the output array. However, filter should be used to... well, filter that array, meaning that is should not modify it, just return a sub-set of it. Instead, you might want to use forEach. However, taking into accound the next bullet, probably you want to use map.
You are modifying the array passed to the checkName function. This is confusing and can lead to hard-to-find bugs. Instead, make your function "pure", meaning that it should not mutate its inputs, instead just return the data you need from it.
I would suggest some implementation like this one:
checkName(output){
return output.map((NewData) => {
// find the old data item corresponding to the current NewData
const OldData = this.props.elements.find(x => x.key === NewData.key);
if (OldData) {
// If found, return a clone of the new data with the old data name
// This uses the spread syntax: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
return {
...NewData, // Clone the NewData object
name: OldData.name, // set the value found in OldData.name in the "name" field of the cloned object
number: OldData.number, // You can do the same for each field for which you want to replace the value cloned from NewValue
};
} else {
// Otherwise, just return a clone of the NewData
return { ...NewData };
}
}
}
The usage would be like this:
const named = this.checkName(product.rows)
Be aware that the product.rows array won't be modified!
You can get keys and values of the old object.
const keys = Object.keys(oldObject);
const values = Object.values(oldObject);
// or
const [keys, values] = Object.entries(oldObject);
After, you will create a loop with all keys of oldObject, and insert in newObject like a array.
keys.forEach( (key, index) => newObject[key] = values[index]);
// or
for (const [key, value] of Object.entries(object1)) {
newObject[key] = value
}
Use map like this.
checkName(output){
return output.map(( NewData) =>{
this.props.elements.forEach((OldData) => {
if (NewData.key == OldData.key) {
NewData.name = OldData.name;
NewData.number = OldData.number;
}
})
return NewData;
})
// return output;
}

Set arguments dynamically with Promise.all().then()

The code below works for me
Promise.all([first, second, third]).then([first, second, third] => {
console.log(second);
});
I know that console.log(second) will give me the value with the key second.
My promises are dynamically set and now it looks like below:
let collection = [second, third];
Promise.all(collection).then((collection) => {
console.log(collection);
});
In this example I set two values in collection. In real life it can include more or less values.
When I use console.log(collection) it will output collection[0] and collection[1]. In this case I don't know what which value collection[1] is.
Question
How can I, like my first example, have something like named dynamically arguments like collection['second'] or similar?
As we want to access the value dynamically, set collection to an empty object first. Then, use the keys from collection to pass all its Promise-values to Promise.all. Then, map back the fulfilled values and then, we can access collection's value by some key.
let collection = {}
for (let i = 0; i < 3; i++) {
collection[`key${i}`] = Promise.resolve(i)
}
let collectionKeys = Object.keys(collection)
Promise.all(collectionKeys.map(key => collection[key]))
.then(values => {
let collectionFulfilled = collectionKeys.reduce((obj, key, i) => {
obj[key] = values[i]
return obj
}, {})
console.log(collectionFulfilled)
})
If you pass your promises embedded inside an object with a single key, you could use that for it's name, and then with a simple helper function reverse the values & keys from this.
With the new ES6 you can then just pass like -> [{one}, {two}, {three}] etc.
Below is an example with a helper function called namedPromiseAll.
function namedPromiseAll(named) {
const pcollection =
named.map(m => Object.values(m)[0]);
const ncollection =
named.map(m => Object.keys(m)[0]);
return Promise.all(pcollection).then((c) => {
return c.reduce((a,v,ix) => {
a[ncollection[ix]] = v;
return a;
}, {});
});
}
const second = Promise.resolve(2);
const third = Promise.resolve(3);
const collection = [{second}, {third}];
namedPromiseAll(collection).then(console.log);

Converting simple logic using filter in javascript

I am new to ES6 features and trying to apply filter logic in my code. My current code with forEach works but I am applying filter something like below:
export function filterContactList(itemArray: any[]) {
const list = [];
if (itemArray.length > 0) {
itemArray.forEach(item => {
if (contactIds.includes(item.id)) {
list.push(item);
}
});
}
return list;
}
// what I am trying to replace with:
itemArray(item => contactIds.includes(item.id))
You could filter the array.
return itemArray.filter(item => contactIds.includes(item.id));
The filter function works by creating a new array containing only the elements that pass your conditions.
let list = itemArray.filter(item => contactIds.includes(item.id));
This will create a new array named list which contains elements from itemArray that pass the condition you set.
var contactIds = "test";
function filterContactList(itemArray: any[]) {
return itemArray.filter(item => contactIds.includes(item.id));
}
All are working fine but as per my knowledge includes and filter will not work for IE.
so we can replace with custom filter function.
var customFilter = function (itemArray, contactIds) {
var list = [];
for (var i = 0; i < itemArray.length; i++) {
var item=itemArray[i];
if (contactIds.indexOf(item.id)>-1) {
list.push(item);
}
}
return list;
}
Use .filter() method of array which will create a new array with all elements that pass the test implemented by the provided function like this:
function filterContactList(itemArray){
const contactIds = [1,2,3];
return itemArray.filter(item => contactIds.includes(item.id));
}
console.log(filterContactList([{id:1},{id:2},{id:3},{id:4},{id:5}]));

Test to check if array is reversed in place

I have a method which I have put on the array prototype that reverses the array (this is done for learning purposes only). This method should reverse the array in place.
Array.prototype.yarra = function () {
for (let left=0, right=this.length-1; left<right; left++, right--) {
[this[left], this[right]] = [this[right], this[left]]
}
return this
};
I have written some tests to check if the method works as expected.
describe('yarra', function () {
it('should reverse an array in place and return it', function () {
var arr = [1,2,3];
var reversedArr = arr.yarra();
reversedArr.should.eql([3,2,1]);
arr.should.equal.reversedArr;
[4,5,6].yarra().should.eql([6,5,4]);
});
});
I realise the tests don't work as expected as I reversed the array out of place and returned a new array, and it still passed. Also, because var reversedArr = arr.yarra() means arr will always equal reversedArr, so it doesn't really check for anything.
How would I write a test that can check if the array is reversed in place?
const assert = require('assert');
Array.prototype.yarra = function () {
for (let left=0, right=this.length-1; left<right; left++, right--) {
[this[left], this[right]] = [this[right], this[left]]
}
return this
};
describe('yarra1', () => {
it('should reverse an array in place and return it', () => {
let arr = [1,2,3];
let rev = [3,2,1];
let reversedArr = arr.yarra();
for(let i =0;i<arr.length;i++){
assert(reversedArr[i]===rev[i])
}
});
});
describe('yarra2', () => {
it('should reverse an array in place and return it', () => {
let arr = [1,2,3];
let rev = [3,2,1];
let reversedArr = arr.yarra();
assert(reversedArr.toString() === rev.toString())
});
});

js map why is not changing my value with return

I'm doing map with a variable, and doing a return to change his value, but it's not working, the value for the whole array is the same:
//resultValues = processValues(table,resultValues,'toClient');
resultValues.map ( (record) => {
record = processValues(table,record,'toClient');
return record;
});
return Promise.resolve(resultValues); // does not change
so I had to create another variable to be able to have a change on the array. why is this behavoiur? it's normal in map ?; is there another option with lodash by example to don't need create a second variable?
let newResult = [];
resultValues.map ( (record) => {
record = processValues(table,record,'toClient');
newResult.push(record); // with this changes are sent to new var
//return record;
});
// return Promise.resolve(resultValues);
return Promise.resolve(newResult);
Array.map returns a new array instance where each element inside it is transformed:
let ret = resultValues.map (record => processValues(table,record,'toClient'));
return Promise.resolve(ret);
Map returns a new array. You could literally do:
const newArr = resultValues.map ( (record) => {
record = processValues(table,record,'toClient');
return record;
});
Please read the first sentence of the MDN web docs for map().

Categories

Resources