So I have an issue that requires me to map an array of names to an object with a property of name.
The following code is in question:
this.planNames.map((name,index) => {
this.tempdata[index].name = name;
}),
Here is an example of the array.
tempdata: any = [
{
name: 'Mix and match',
title: 'Single-line plans for voice messaging and data.',
desc:
'A great plan option for businesses that want each line on its own plan. These plans have no maximum line caps.',
},
{
name: 'Flexible',
title: 'Multi-line plans for when one size does not fit all.',
desc:
'A great plan option for up to 10 phones with different unlimited data needs',
}
Any idea using arrow functions would be great as I am learning more about these myself.
There should be some changes in your map function.
this.planNames.map((item,index) => {
this.tempdata[index].name = item.name;
});
console.log(this.tempData)
[].map returns a new array containing the result of each of the original array elements passed through the callback function. So, you don't need to create a temporary array beforehand - the result of the map function will contain what you need.
const newTempData = this.planNames.map((name, index) => {
return { ...tempdata[i], name }
});
You don't generally mutate data in a .map function. If you're interested in mutating the original data structure, tempdata, you should just use a standard [].forEach.
tempdata.forEach((data, index) => {
data.name = this.planNames[index];
});
The map function is only to replace data by others in array.
If you want to update other array data, you should use a for loop:
const tempdata = [
{
name: 'Mix and match',
title: 'Single-line plans for voice messaging and data.',
desc:
'A great plan option for businesses that want each line on its own plan. These plans have no maximum line caps.',
},
{
name: 'Flexible',
title: 'Multi-line plans for when one size does not fit all.',
desc:
'A great plan option for up to 10 phones with different unlimited data needs',
}
];
const planNames = ['a', 'b'];
for(let i = 0; i < planNames.length; i++) {
tempdata[i].name = planNames[i];
}
console.log(tempdata);
Related
I am working on something where I take data from 2 different APIs that I have no control of and I want to combine the results in the most efficient way.
One of the arrays hold some assets, lets say books, the other one holds a transaction for the said book. Here is an example:
{
author: {name: 'J.K. Rowling', },
assetName: 'Book1'
}]
const array2 = [
{from: 'John',
to: 'Sarah,
price: 10,
timeStamp: 123,
assetName: 'Book1',
authorName: 'J.K. Rowling'
}]
Note that to find the corresponding transaction for a given book, you need both assetName and authorName to match - you can own more than one book of the same author and you can own two books with the same name but a different author but an author has only one book with a given name, thus finding the corresponding transaction to an asset requires both fields to match and there are no other unique identifiers.
The naive approach is to iterate over one of the arrays and for each entry to check in the second array to find the transaction but that looks like it will take too long to execute if the arrays are of substantial size.
I was wondering what better solutions can you think of for merging two objects with different structure that is efficient?
Well, if author.name + assetName form an id, you could iterate over array1 once & create a Map with keys being author.name + assetName & vales being original objects.
Then you could iterate over array2 once as well & enrich it whatever way you want. All lookups in the second iteration will be fast since you will access the Map instead of searching in array.
const indexedArray1 = new Map();
array1.forEach(data => indexedArray1.set(data.author.name + data.assetName, data);
const enrichedArray2 = array2.map(transaction => {
const relatedBook = indexedArray1.get(transaction.authorName + transaction.assetName);
// Merge relatedBook & transaction the way you want here
});
I often do the following when merging arrays
The time complexity is O(n)
const array1 = [{
author: {name: 'J.K. Rowling' },
assetName: 'Book1'
}]
const array2 = [{
from: 'John',
to: 'Sarah',
price: 10,
timeStamp: 123,
assetName: 'Book1',
authorName: 'J.K. Rowling'
}]
const array2_map = {}
array2.forEach(e => {
const key = `${e.assetName}:${e.authorName}`
if (!array2_map[key]) array2_map[key] = []
const { from, to, price, timeStamp } = e
array2_map[key].push({
from,
to,
price,
timeStamp
})
})
const merged_array = array1.map(e => ({
...e,
transaction: array2_map[`${e.assetName}:${e.authorName}`] || []
}))
I have 3 different arrays which contain an object with public holiday data (based on the region in the world e.g Mexico, Canada, US). I want to organise the data (store a combination of it all in its own array) so that if a regions share the same public holiday for example name: 'Christmas Day' date: 2021-12-25 then it only stores this once rather than for each region which is what its doing at the moment. The main issue is theres a problem with a lot of duplicate data inside allPublicHolidays function & i'm getting lost when it comes to the checkIfSame forEach loop as there is probably a much nicer way to do this.
The array data looks like this per region:
[
{
date: '2021-05-31 00:00:00',
name: 'Spring bank holiday',
},
{
date: '2021-12-25 00:00:00',
name: 'Christmas Day',
},
{
date: '2021-12-26 00:00:00',
name: 'Boxing Day',
}
]
The idea I had is to use a forEach loop for each region which pushes the data from each to its own array but checks the array each time it processes a holiday to make sure it doesn't already exist within the array. Before pushing it calls a function to check if the name data is the same as the array.
Here is what I have so far:
const regionUS = usArrayData;
const regionMX = mxArrayData;
const regionCA = caArrayData;
let allPublicHolidays = [];
function checkIfSame(name1, array) {
let boolean = false;
if (array) {
array.forEach((arr) => {
if (name1 == arr.name) {
boolean = true;
}
})
}
return boolean;
}
regionUS.forEach((USholiday) => {
if (!checkIfSame(USholiday.name, allPublicHolidays)) {
allPublicHolidays.push(USholiday);
}
});
regionMX.forEach((MXholiday) => {
if (!checkIfSame(MXholiday.name, allPublicHolidays)) {
allPublicHolidays.push(MXholiday);
}
});
Any help with storing all data in one array minus duplicates based on object.name && object.date would be really appreciated.
Thank you
Using .map(), .reduce(), .filter() functions, how can I write an efficient routine that can derive all Radio stations that have a .genre that exists in the Popular genres set AND a .tag in the Tags set?
// Radio stations
const stations = [
{
title: 'BBC Radio 1',
genre:['Popular', 'Rnb', 'Hip Hop', 'Dance'],
tag: ['bbc', 'radio 1', 'uk']
},
{
title: 'Classic FM',
genre:['Classical', 'Orchestra'],
tag: ['bbc', 'uk']
},
]
// Popular genres
const popular = [
'Popular',
'House',
'Chillout',
'Top 40',
'Drum And Bass'
]
// Tags
const tags = [
'bbc',
'uk'
]
I believe that this is a common pattern which doesn't seem to be well documented. My own attempts have involved writing nested loops which I believe could be cleaner. My dataset contains ~22,000 entries (I can tweak this to performance), and searches upon key press. This will run offline and I cannot use a database, even a local one. I would like to use the; .map(), .reduce(), .filter() functions, even though I understand that these may impose function call overhead and that I could use a binary tree.
You can indeed use filter, but then some and includes:
let filtered = stations.filter(station =>
station.genre.some(genre => popular.includes(genre)) &&
station.tag.some(tag => tags.includes(tag))
);
You can use simply .filter, and check two things:
Is there a tag key at all?
If there is a tag key, are there any values for it?
Like So:
const stationsWithTags = stations.filter(e => e.tag && e.tag.length > 0);
Then use a for loop nested inside another for loop, to check each item in genre against each item in popular. When a match is found, the return adds to the filtered variable, exits the loop, and the next station is evaluated.
Try running the full code below:
// Radio stations
const stations = [
{
title: 'BBC Radio 1',
genre:['Popular', 'Rnb', 'Hip Hop', 'Dance'],
tag: ['bbc', 'radio 1', 'uk']
},
{
title: 'Classic FM',
genre:['Classical', 'Orchestra'],
tag: ['bbc', 'uk']
}
]
// Popular genres
const popular = [
'Popular',
'House',
'Chillout',
'Top 40',
'Drum And Bass'
]
// Tags
const tags = [
'bbc',
'uk'
]
const stationsWithTags = stations.filter(e => e.tag && e.tag.length > 0);
const popularStationsWithTags = stationsWithTags.filter(e => {
if (e.genre){
//Check each item in 'genre' against each item in 'popular'
for (let i = 0; i < e.genre.length; i++){
for (let j = 0 ; j < popular.length; j++){
if (e.genre[i] === popular[j]){ //If genre is in 'popular', this item passes filter
return true;
}
}
}
}
})
console.log(popularStationsWithTags);
Well I am stuck here and I would appreciate some directions of methods I can accomplish this with.
I got an array with questions:
questions: [
{
question: 'lala',
answer: 'papa',
categories: ['Handla']
},
{
question: 'xxxx',
answer: 'yyyy',
categories: ['Reklamation']
}
]
Based on the categories I want to be able to list the questions accordingly when filtering.
So lets say I want to filter on 'Handla' I should be able to loop out all the questions that has the value 'Handla' matched in the categories array.
mapping through the questions array and doing returning them with an if/else statement will work but im not sure this is the optimal way.
Summary: I want to iterate through questions and pick out objects that matches with my desired category query.
My desired output when requesting "Reklamation" should be
const desiredArray = [{
{
question: 'xxxx',
answer: 'yyyy',
categories: ['Reklamation']
}
}]
Use Array#filter and check if the category (Reklamation in the example) is found in the categories array using Array#includes:
const questions = [{"question":"lala","answer":"papa","categories":["Handla"]},{"question":"xxxx","answer":"yyyy","categories":["Reklamation"]}];
const result = questions.filter(({ categories }) => categories.includes('Reklamation'));
console.log(result);
Try this
var result = questions.filter((item) => item.categories.find((cat) => cat === 'Reklamation'))
You can use array#filter with array.indexOf.
var data = {questions: [{question: 'lala',answer: 'papa',categories: ['Handla']},{question: 'xxxx',answer: 'yyyy',categories: ['Reklamation']}]},
category = 'Reklamation',
result = data.questions.filter(({categories}) => categories.indexOf(category) > -1);
console.log(result);
I would create a reusable function that you can call whenever you want to search by category:
const filterByCategory = (questions, category) => {
return questions.filter(q => q.categories.includes(category))
}
filterByCategory(questions, 'Reklamation');
filter takes a callback that returns true if you want to keep the element.
Please see the filter and includes docs for more info
I do get my data from mongoDB with
Content.find({}).fetch()
So there is an array with 1000 documents. Every document has a category field.
const data = [
{
title: 'Article 1',
category: 'cars'
},
{
title: 'Article 2',
category: 'vegetables'
}
]
Now I would like to display a list with the documents organized in categories (Getting an own list for each category).
I think the best way I should go is to create a map. But I do not know how to do that.
This is what I am doing:
First I've hardcoded the categories (knowing this is the worst thing I can do)
Then...
categories.map(category => {
return (<List data={data.filter(d => d.category === category)} />)
}
With this I will go through 30 categories and do a filter on my data 30 times. I think it would be smarter to create a kind of sorted dataset once at the beginning.
If you'd prefer using lodash, then you can sort your data set using sortBy
_.sortBy(data, ['category', 'title']);
data.map(doc => ( console.log(doc); ));
This will sort your data ascending first by category and then by title.
OR if you want to break your items into arrays based on category use groupBy:
_.groupBy(data, 'category');
_.each(data, itemsByCategory => {
return <List data={itemsByCategory} />;
});
Since aggregating data on mongodb is not an option, I would create a map on the client side by looping once over the data, like:
var titlesByCategory = {};
for (let value of data) {
if (titlesByCategory[data.category]) {
titlesByCategory[value.category].push(value.title);
}
else {
titlesByCategory[value.category] = [value.title];
}
}
You can then access the array of titles of a given a category just using the category as a key; for instance titlesByCategory[vegetables] will return the array of vegetables over which you can do loop/map or whatever you need.
using underscoreJS
_.groupBy(data, 'length');