Figuring out .map() method - javascript

Learning JS here, I have a code that already does what I need but wanted to see if I could do it with the .map() method.
In a nutshell, this code appends a table to a web page using the data stored in filteredSightings.
let filteredSightings = [{
datetime: "1/1/2010",
city: "benton",
state: "ar",
country: "us",
shape: "circle",
durationMinutes: "5 mins.",
comments: "one bright green light at my front door."
},
{
datetime: "1/1/2010",
city: "bonita",
state: "ca",
country: "us",
shape: "light",
durationMinutes: "13 minutes",
comments: "Three bright red lights witnessed floating"
},
... and so on
so this does the job:
let tbody = d3.select("tbody");
filteredSightings.forEach((sight) => {
let row = tbody.append("tr");
Object.entries(sight).forEach(([key, value]) => {
let cell = row.append("td");
cell.text(value);}
);
});
And now I'm trying to change it so that i can use .map() but can't find a way to "translate" forEach(([key, value]) into .map().
This is with what I came up so far:
filteredSightings.map(sight => tbody.append("tr").append("td").text(sight.datetime));

Related

Looping ant design tag color in React Js

I use Ant Design and data which coming from API. I assume the data like this
data = [
{
name: "John",
job: "Freelancer",
},
{
name: 'Bob',
job: 'UI Designer'
},
{
name: 'Sam',
job: 'CEO'
},
{
name: 'Alex',
job: 'Mobile Dev'
},
{
name: 'Jess',
job: 'Web Dev'
},
];
I want to return the job with Tag from Ant Design which the tag has a different color
<Tag color="green">green</Tag>
<Tag color="cyan">cyan</Tag>
I have looped the data. but I don't know how to make the data have a different color tag
data.map((el) => {
//This example doesn't have color
return <Tag>{el.job}</Tag>
})
How to achieve that ? And sorry i'm not good enough in English. I hope you understand what i mean
Or you can visit code sandbox here
In your data, add a property something like tagColor for each object.
data = [
{
name: "John",
job: "Freelancer",
tagColor: "red"
},
{
name: 'Bob',
job: 'UI Designer'
tagColor: "green"
},
{
name: 'Sam',
job: 'CEO'
tagColor: "blue"
},
];
Then in the loop, use that property to dynamically add colors. Like,
data.map((el) => {
return <Tag color={el.tagColor}>{el.job}</Tag>
});
Updated
If the colors can be random, you can place all your colors in an array. And you can pick colors one by one using index or even a randomiser. Something like,
const colors = ["red", "blue", "green"];
data.map((el, i) => {
return <Tag color={colors[(i%colors.length)]}>{el.job}</Tag>
});
It will pick colors in the array one by one based on index.

Adding Images to Objects

I am working on a project where we I have an array full of objects. It stores movie information, and I would like to add an image of the poster onto the object as well. Below is an example of my code. I have functions that searches through the array for specific movies based on given information, and returns the information. I would like it to return an image with it as well. This information then gets printed onto a website. Here is the code:
var allMovies = [
{
Title: "Green Book",
Year: 2019,
Director: "Peter Farrelly",
Winner: "yes",
Genre: "Biography, Comedy, Drama"
},
{
Title: "Black Panther",
Year: 2019,
Director: "Ryan Coogler",
Winner: "no",
Genre: "Action, Sci-Fi"
},
and there is more code after this, but it is too long to add the whole code. Is there a way to add an image, and have it be returned with this information, and then be printed onto a page?
Similar to what #rid said, but ill add a bit more, maybe it will help.
so your array is:
var allMovies = [
{
Title: "Green Book",
Year: 2019,
Director: "Peter Farrelly",
Winner: "yes",
Genre: "Biography, Comedy, Drama",
Image:"https:website.com/images/image.jpg"
},
{
Title: "Black Panther",
Year: 2019,
Director: "Ryan Coogler",
Winner: "no",
Genre: "Action, Sci-Fi",
Image:"https:website.com/images/image.jpg"
}
]
Now you can loop through the array and use template literals to create your HTML output, it could be done like this:
let output='';
allMovies.forEach(Movie=>{
//we use template literals here to make things easier
output+=`<h1>Title: ${Movie.Title}</h1>
<img src="${Movie.Image}" alt="Movie Image">
<p>Year: ${Movie.Year}<p>
<p>Director: ${Movie.Director}</p>
<p>Winner: ${Movie.Winner}</p>
<p>Genre: ${Movie.Genre}</p>
`
})
const div =document.querySelector("yourdiv");
div.innerHTML=output;
I hope this helped :)
You have to add the url of the image.
Like this,
var allMovies = [
{
Title: "Green Book",
Year: 2019,
Director: "Peter Farrelly",
Winner: "yes",
Genre: "Biography, Comedy, Drama",
Image_url: "https://www.something.com/something/something.jpg"
},
{
Title: "Black Panther",
Year: 2019,
Director: "Ryan Coogler",
Winner: "no", Genre: "Action, Sci-Fi",
Image_url: "https://www.something.com/something/something.jpg"
},

Fetch specific informations from complex json object

I want to fetch year, category, id and share of a particular nobel prize winner from the json data, by giving firstname and surname as raw input. I am able to get id and share easily from the below code but how can I get year and category.
Here is my code:
var json = {"prizes":
[{"year":"2018",
"category":"physics",
"overallMotivation":"\u201cfor groundbreaking inventions in the field of laser physics\u201d",
"laureates":[
{"id":"960",
"firstname":"Arthur",
"surname":"Ashkin",
"motivation":"\"for the optical tweezers and their application to biological systems\"",
"share":"2"},
{"id":"961",
"firstname":"G\u00e9rard",
"surname":"Mourou",
"motivation":"\"for their method of generating high-intensity, ultra-short optical pulses\"",
"share":"4"},
{"id":"962",
"firstname":"Donna",
"surname":"Strickland",
"motivation":"\"for their method of generating high-intensity, ultra-short optical pulses\"",
"share":"4"}
]}
]};
var winner = json.prizes.reduce((acc, winners) =>
(acc.push(...winners.laureates), acc), []).find(i => i.id === '960')
console.log(winner);
For the sake of completeness, I have added miultiple prizes in my test input. I hope that is allright. Try this code.
const input = {
prizes: [
{
year: "2018",
category: "physics",
overallMotivation:
"\u201cfor groundbreaking inventions in the field of laser physics\u201d",
laureates: [
{
id: "960",
firstname: "Arthur",
surname: "Ashkin",
motivation:
'"for the optical tweezers and their application to biological systems"',
share: "2"
},
{
id: "961",
firstname: "G\u00e9rard",
surname: "Mourou",
motivation:
'"for their method of generating high-intensity, ultra-short optical pulses"',
share: "4"
},
{
id: "962",
firstname: "Donna",
surname: "Strickland",
motivation:
'"for their method of generating high-intensity, ultra-short optical pulses"',
share: "4"
}
]
},
{
year: "2019",
category: "chemistry",
overallMotivation:
"\u201cfor groundbreaking inventions in the field of laser physics\u201d",
laureates: [
{
id: "960",
firstname: "Arthur",
surname: "Ashkin",
motivation:
'"for the optical tweezers and their application to biological systems"',
share: "2"
},
{
id: "961",
firstname: "G\u00e9rard",
surname: "Mourou",
motivation:
'"for their method of generating high-intensity, ultra-short optical pulses"',
share: "4"
},
{
id: "123",
firstname: "Donna",
surname: "Strickland",
motivation:
'"for their method of generating high-intensity, ultra-short optical pulses"',
share: "6"
}
]
}
]
};
function find(firstName, surname) {
return input.prizes.map(prize => {
const filteredLaureate = prize.laureates.filter(
laureate =>
laureate.firstname === firstName && laureate.surname === surname
);
return filteredLaureate.map(i => {
return {
id: i.id,
share: i.share,
category: prize.category,
year: prize.year
};
});
}).flat();
}
const response = find("Donna", "Strickland");
console.log(response);
Try this code.
let winners = [];
json.prizes.forEach(e => {
let data = { year: e.year, category: e.category };
const laureates = e.laureates.find( item => {
return item.firstname === 'Arthur' && item.surname === 'Ashkin';
});
data = { ...data, ...laureates };
winners.push(data);
});
console.log(winners);
The code above will give output like this:
[{
category: "physics",
firstname: "Arthur",
id: "960",
motivation: "\"for the optical tweezers and their application to biological systems\"",
share: "2",
surname: "Ashkin",
year: "2018"
}]
Remember, the code above will not perform very good when the dataset is large.

Using reduce to count groups of data within groups of data

As the title says, I'm trying to count groups of data within groups of data: My logic is to group all the data into states, then group date into years. so that the output should look like something like:
state,year,count
mo,1910,2
in,1910,1
il,1910,3
or,1910,4
co,1910,2
nd,1910,1
...
mo,1911,5
in,1911,4
il,1911,6
or,1911,2
co,1911,8
The CSV I'm using has a lot more columns that needed, I'm only interested in the columns state and year. My code below isn't working, any help would be great.
const countStates = filteredData.reduce((m, d) => {
if(!m[d.year]){
m[d.year] = {...d, count: 1};
return m;
}
m[d.state];
m[d.year];
m[d.year].count += 1;
return m;
},{});
const countedStates = Object.keys(countStates).map((k) => {
const item = countStates[k];
return {
state: item.state,
year: item.year,
count: item.count
}
})
Edit
Example of the dataset I'm using:
datetime,city,state,country,shape,duration (seconds),duration (hours/min),comments,date posted,latitude,longitude
10/10/1949 20:30,san marcos,tx,us,cylinder,2700,45 minutes,"This event took place in early fall around 1949-50. It occurred after a Boy Scout meeting in the Baptist Church. The Baptist Church sit",4/27/2004,29.8830556,-97.9411111
10/10/1949 21:00,lackland afb,tx,,light,7200,1-2 hrs,"1949 Lackland AFB&#44 TX. Lights racing across the sky & making 90 degree turns on a dime.",12/16/2005,29.38421,-98.581082
10/10/1955 17:00,chester (uk/england),,gb,circle,20,20 seconds,"Green/Orange circular disc over Chester&#44 England",1/21/2008,53.2,-2.916667
10/10/1956 21:00,edna,tx,us,circle,20,1/2 hour,"My older brother and twin sister were leaving the only Edna theater at about 9 PM&#44...we had our bikes and I took a different route home",1/17/2004,28.9783333,-96.6458333
10/10/1960 20:00,kaneohe,hi,us,light,900,15 minutes,"AS a Marine 1st Lt. flying an FJ4B fighter/attack aircraft on a solo night exercise&#44 I was at 50&#44000&#39 in a "clean" aircraft (no ordinan",1/22/2004,21.4180556,-157.8036111
10/10/1961 19:00,bristol,tn,us,sphere,300,5 minutes,"My father is now 89 my brother 52 the girl with us now 51 myself 49 and the other fellow which worked with my father if he&#39s still livi",4/27/2007,36.5950000,-82.1888889
10/10/1965 21:00,penarth (uk/wales),,gb,circle,180,about 3 mins,"penarth uk circle 3mins stayed 30ft above me for 3 mins slowly moved of and then with the blink of the eye the speed was unreal",2/14/2006,51.434722,-3.18
10/10/1965 23:45,norwalk,ct,us,disk,1200,20 minutes,"A bright orange color changing to reddish color disk/saucer was observed hovering above power transmission lines.",10/2/1999,41.1175000,-73.4083333
10/10/1966 20:00,pell city,al,us,disk,180,3 minutes,"Strobe Lighted disk shape object observed close&#44 at low speeds&#44 and low altitude in Oct 1966 in Pell City Alabama",3/19/2009,33.5861111,-86.2861111
10/10/1966 21:00,live oak,fl,us,disk,120,several minutes,"Saucer zaps energy from powerline as my pregnant mother receives mental signals not to pass info",5/11/2005,30.2947222,-82.9841667
10/10/1968 13:00,hawthorne,ca,us,circle,300,5 min.,"ROUND &#44 ORANGE &#44 WITH WHAT I WOULD SAY WAS POLISHED METAL OF SOME KIND AROUND THE EDGES .",10/31/2003,33.9163889,-118.3516667
10/10/1968 19:00,brevard,nc,us,fireball,180,3 minutes,"silent red /orange mass of energy floated by three of us in western North Carolina in the 60s",6/12/2008,35.2333333,-82.7344444
10/10/1970 16:00,bellmore,ny,us,disk,1800,30 min.,"silver disc seen by family and neighbors",5/11/2000,40.6686111,-73.5275000
And the code I used to filter out the data:
fs.createReadStream('./data/scrubbed.csv')
.pipe(readCSV())
.on('data', (data) => CSV.push(data))
.on('end', () => {
let data = CSV.map((d) => {
return {
year: new Date (d.datetime).getFullYear(),
state: d.state,
country: d.country
}
});
filteredData = data.filter((d) => {
return d.state !== "" && d.country === "us"
})
Which returns this (an example of the dataset):
[ { year: 1949, state: 'tx', country: 'us' },
{ year: 1956, state: 'tx', country: 'us' },
{ year: 1960, state: 'hi', country: 'us' },
{ year: 1961, state: 'tn', country: 'us' },
{ year: 1965, state: 'ct', country: 'us' }...
The above is what I'm trying to group twice using reduce
The below code gets an array of states with the year and using reduce we are getting the count of each state grouped by year as
var data = [
{ year: '1910', state: 'mo', country: 'us' },
{ year: '1910', state: 'in', country: 'us' },
{ year: '1910', state: 'il', country: 'us' },
{ year: '1910', state: 'mo', country: 'us' },
{ year: '1911', state: 'in', country: 'us' },
{ year: '1911', state: 'il', country: 'us' },
{ year: '1911', state: 'mo', country: 'us' },
{ year: '1911', state: 'in', country: 'us' }
];
var organizedData = data.reduce((acc, val, index) => {
acc[val.state] = acc[val.state] || {};
acc[val.state][val.year] = (+acc[val.state][val.year] || 0) + 1;
return acc;
}, {});
console.log(organizedData);

Display filtered array with multiple options in Vue

Apologies if this is answered elsewhere. Been googling and searching on here without any luck. Closest answer I could find is here but it requires quite a bit of rework with the setup I've got.
I'm trying to filter an array based on multiple inputs of a user. My demo assumes two inputs but the actual app should approx be five. JSFiddle
HTML
<div id="app">
<h2>Continent</h2>
<div v-for="filter in filters.continent">
<input type="checkbox" :value="filter" v-model="search.continent"> {{filter}}
</div>
<h2>Budget</h2>
<div v-for="filter in filters.budget">
<input type="checkbox" :value="filter" v-model="search.budget"> {{filter}}
</div><br/>
<p>You would like to live in {{search.continent}} and your budget is {{search.budget}}</p>
<div v-for="country in filteredCountries">
{{country.name}}
</div>
</div>
JS
new Vue({
el: "#app",
data() {
return {
search: {
continent: [],
budget: []
},
filters: {
continent: ['Europe', 'Asia', 'North America'],
budget: ['Low', 'Medium', 'High'],
},
countries: [
{
name: "Sweden",
continent: "Europe",
budget: ["Medium", "High"],
},
{
name: "Hong Kong",
continent: "Asia",
budget: ["Medium", "Low"],
},
{
name: "Thailand",
continent: "Asia",
budget: ["Low"],
},
{
name: "Canada",
continent: "North America",
budget: ["Medium", "High"],
},
{
name: "US",
continent: "North America",
budget: ["Medium", "Low"],
}
]
}
},
computed: {
filteredCountries: function(){
return this.countries.filter((country) =>
this.search.budget.some(el => country.budget.includes(el)),
)
},
}
})
In my actual app I'm using different components for the results and filters with an event bus that sends a payload with search data that feeds into the filtered computed property.
I hope someone's able to point me in the right direction with an approach that hopefully doesn't require more complexity as additional (similar array based) filter options are added.
Still trying to get a grasp on Javascript so apologies for the newb question!
Edit: Baboo_'s answer is really close to what I want but it seems I may have overlooked two things now that I've tried his fiddle. Firstly, the filters should be able to accept an array of options. I've updated my Fiddle to show this.
The intended effect is that the filters are constantly updating the results like a sidebar filter. It's purely optional. I understand that my Fiddle doesn't assume so because everything's hidden from the get-go but my intention is to include a hidden filter that has everything checked in. Every other input is to simply just refine the results in real time.
You can filter the countries successively by budget and continent like this:
computed: {
filteredCountries: function(){
return this.countries
.filter(country => this.search.budget.includes(country.budget))
.filter(country => this.search.continent.includes(country.continent));
},
}
Here is the fiddle.

Categories