Find a Relation array and object - javascript

let data = [{
name: "Sarah",
year: ["1924", "1936", "1948", "1960", "1972", "1984", "1996", "2008", "2020", "2032"]
},
{
name: "Ann",
year: ["1925", "1937", "1949", "1961", "1973", "1985", "1997", "2009", "2021", "2033"]
}
];
we assign an array and inside the array has two objects and every object has got another array.
I want to ask user her birth year and select her name from object value from the name.
for example, if she was born in 1949 her name must be Ann or if she was born in 1960 her name must be Sarah.
I am thinking about two days but I couldn't solve this problem.
I don't want to write code if/else or case switches state. is there another code option?
I want to make a correlation between name and years.
I hope I explain well..

I think this is what you're looking for
let data = [{
name: "Sarah",
year: ["1924", "1936", "1948", "1960", "1972", "1984", "1996", "2008", "2020", "2032"]
}, {
name: "Ann",
year: ["1925", "1937", "1949", "1961", "1973", "1985", "1997", "2009", "2021", "2033"]
}];
function yearToName(year) {
return data.find(x => x.year.includes(year)).name;
}
console.log(yearToName("1936"))
console.log(yearToName("1937"))

You could accomplish this using Array.find and Array.includes: find the entry whose years include what you're looking for, then pluck the name from it. Something like this:
function getName (searchYear) {
const entry = data.find(({year}) => year.includes[searchYear]);
return entry?.name;
}

This is maybe not exactly what you wanted, but by setting up a lookup structure you can speed up and simplify the followin search steps. It will behave in a stable way, i. e. for years, where no name was defined an "undefined" will be returned.
let data = [
{name:"Sarah",
year:["1924", "1936", "1948", "1960", "1972", "1984", "1996", "2008", "2020", "2032"]},
{name:"Ann",
year:["1925", "1937", "1949", "1961", "1973", "1985", "1997", "2009", "2021", "2033"]}
];
// setup a looup structure:
data.lookup=data.reduce((a,{name,year})=>(year.forEach(y=>a[y]=name),a),{})
// run a test over many years:
for (let y=1923;y<2034;y++) data.lookup[y] && console.log(y,data.lookup[y]);

You can write a function which will get the name
With these methods
Array.find - to get the single object from the array of objects
Array.includes - to find the passed year present in the array of year
? - Optional chaining , in order getting an error, it will return undefined or null
?? - Nullish coalescing operator, to return the right side when the left side is null or undefined
let data = [{
name: "Sarah",
year: ["1924", "1936", "1948", "1960", "1972", "1984", "1996", "2008", "2020", "2032"]
}, {
name: "Ann",
year: ["1925", "1937", "1949", "1961", "1973", "1985", "1997", "2009", "2021", "2033"]
}];
const getTheName = (year) => data.find(datumn => datumn.year.includes(year))?.name ?? `Don't have a name`
console.log(getTheName('1924')) // Sarah
console.log(getTheName('1949')) // Ann
console.log(getTheName('2020')) //Don't have a name

Related

JavaScript advanced reduce function I can't get my head around {}[iteration]

I just can't understand this concept in the function below:
acc[line[0]]
I really can't get my head around that piece of code, how come it is not be an error and works perfectly? How do you interpret it in English words? In my head it is an empty object acc {} at its first iteration and according to the piece of code is trying to access the iterated line at its first value [0]. How come it works without the need of inverted commas as well? And how does line[0] ended up to be the values of the object?
Here is the full code:
let output = [["mark johansson", "waffle iron", "80", "2"],
["mark johansson", "blender", "200", "1"],
["mark johansson", "knife", "10", "4"],
["Nikita Smith", "waffle iron", "80", "1"],
["Nikita Smith", "knife", "10", "2"],
["Nikita Smith", "pot", "20", "3"]]
let result =output.reduce((acc,line)=>{
acc[line[0]] = acc[line[0]] || []
acc[line[0]].push({
name: line[1],
price: line[2],
quant: line[3]
})
return acc
},{})
console.log(JSON.stringify(result,null,1))
{
"mark johansson": [
{
"name": "waffle iron",
"price": "80",
"quant": "2"
},
{
"name": "blender",
"price": "200",
"quant": "1"
},
{
"name": "knife",
"price": "10",
"quant": "4"
}
],
"Nikita Smith": [
{
"name": "waffle iron",
"price": "80",
"quant": "1"
},
{
"name": "knife",
"price": "10",
"quant": "2"
},
{
"name": "pot",
"price": "20",
"quant": "3"
}
]
}
Maybe if we replace all the dynamic references with hard-coded values from the first array - or line - in output, it will be clearer as to what is going on. This is essentially what the very first iteration of the reducer function is doing:
output.reduce((acc, ["mark johansson", "waffle iron", "80", "2"])=>{
acc["mark johansson"] = acc["mark johansson"] || [];
acc["mark johansson"].push({
name: "waffle iron",
price: "80",
quant: "2"
});
return acc
},{})
Imagine that the first line of the reducer function just said acc["mark johansson"] = acc["mark johansson"]. Since there is no key on the object acc with the name "mark johansson", after evaluating that expression the object acc would look like:
acc = {
"mark johansson": undefined
}
However, by adding || [] onto the end of the expression, we can evaluate whether acc["mark johansson"] is truthy before we actually set the key/value pair. Since undefined is falsy, the || operater kicks in and we get this instead:
acc = {
"mark johansson": []
}
Do you see the difference? With the OR operator we are saying: "either acc["mark johansson"] exists and is therefore truthy, and we set it as itself, OR it is falsy and we set it as a blank array". The rest of the code should be fairly self explanatory. The key/value pair is now guaranteed to exist and we can push the data object to the array. Any further lines which reference acc["mark johansson"] will target the already existing entry.
It helps if you console log after each step to see what is going on:
let output = [
["mark johansson", "waffle iron", "80", "2"],
["mark johansson", "blender", "200", "1"],
["mark johansson", "knife", "10", "4"],
["Nikita Smith", "waffle iron", "80", "1"],
["Nikita Smith", "knife", "10", "2"],
["Nikita Smith", "pot", "20", "3"]
]
let result = output.reduce((acc, line) => {
console.log("acc value at start:", acc, "current line value:", line)
acc[line[0]] = acc[line[0]] || []
//either a new key will appear with an empty array as the value, or the acc will appear unchanged
console.log("acc value after key configuration:", acc)
acc[line[0]].push({
name: line[1],
price: line[2],
quant: line[3]
})
//there will be one new object within one of the keys' array value;
//acc will appear the same in the first console log of the next cycle
console.log("acc after current line values pushed as new object:", acc)
return acc
}, {})
console.log(JSON.stringify(result))
The code snippet above has notes detailing what to look for in the console logs, below is the actual line by line explaination:
//pass {} as the initial value (acc) and cycle through each inner array within output array as current value(line)
let result = output.reduce((acc,line)=>{
//if line[0], which is the name in each inner array, already exists as a key
//then equate key to equal its current value as to not overwrite
//otherwise equate key to equal a new empty array
//basically, whenever line[0] value changes to another name, a new key will be created
acc[line[0]] = acc[line[0]] || []
//now push the other values of the current inner array
//into the key which matches that inner arrays first value(which is the name)
acc[line[0]].push({
name: line[1],
price: line[2],
quant: line[3]
})
//pass the object to the next cycle
return acc
},{})

How to aggregate fields with null data and missing fields in elasticsearch?

I have elasticsearch database as following:
{
"market": "NEW YORK",
"hour_time_stamp": "2019-08-24 01:00:00",
"model_year": 2014,
"num_devices": 28
},
{
"market": "COLUMBIA",
"hour_time_stamp": "2019-08-12 01:00:00",
"model_year": 2019,
"num_devices": 2
},
{
"market": null,
"hour_time_stamp": "2019-08-11 01:00:00",
"model_year": 2016,
"num_devices": 1
},
{
"hour_time_stamp": "2019-08-02 01:00:00",
"model_year": 2014,
"num_devices": 750
},
{
"market": "COLUMBIA",
"hour_time_stamp": "2019-07-12 01:00:00",
"model_year": 2018,
"num_devices": 21
}
As you can see, some values of market are null and in some cases the market field is missing. I have written the following elastic.js query to fetch the market and perform aggregation on it:
let queryBody = ejs.Request()
.size(0)
.query(
ejs.BoolQuery()
.must(
ejs.RangeQuery('hour_time_stamp').gte(this.lastDeviceDate).lte(this.lastDeviceDate)
)
)
.agg(ejs.TermsAggregation('market_agg').field('market').order('sum', 'desc').size(50000)
.agg(ejs.SumAggregation('sum').field('num_devices'))
);
The data that I need is market name and sum of num_devices for that market(since market can be repeated). The query I have written returns only the market where market value is defined. I need to include the missing market as well as "market": null in my bucket. Any ideas how I can do that?

Javascript convert object key names based on mapping

I have a javascript object that is coming from Source1 and I am unable to change its native structure or naming convention. I am using this data to feed into a 3rd party plugin to generate some chart data. This plugin however is using the key names as the identifiers on the chart and they are not descriptive or clear enough.
I am trying to run the object through a conversion function where it will change all of the key names to their defined equivalent.
Here is an example of what I am trying to do:
var obj = [{
SubmissionID: "28935",
MetaCreatedDate: "12 Mar 2018",
Program: "Brand Risk Management",
ViewedByInvestigator: "No",
},
{
SubmissionID: "28936",
MetaCreatedDate: "12 Mar 2018",
Program: "Brand Risk Management",
ViewedByInvestigator: "Yes",
}]
function convertNames(obj){
// Converted names
var map = [{
SubmissionID: 'SubmissionIdentifier',
MetaCreatedDate: 'CreationDate',
Program: 'ProgramName',
ViewedByInvestigator: 'Viewed'
}];
// Loop through the object and convert all key names to their equivalent
for(var prop in obj){
// Convert Here
}
return obj;
}
Desired Output:
[{
SubmissionIdentifier: "28935",
CreationDate: "12 Mar 2018",
ProgramName: "Brand Risk Management",
Viewed: "No",
},
{
SubmissionIdentifier: "28936",
CreationDate: "12 Mar 2018",
ProgramName: "Brand Risk Management",
Viewed: "Yes",
}]
https://jsfiddle.net/hbg4sfqh/7/
I'd combine the .map array method and a function to convert your key names to get the result you want. To convert the key names, you'll want to use bracket notation, so something like: newObj[keyMap[oldKey]] = oldObj[oldKey] should work.
Here's a simple implementation for your example:
const obj = [{
SubmissionID: "28935",
MetaCreatedDate: "12 Mar 2018",
Program: "Brand Risk Management",
ViewedByInvestigator: "No",
}, {
SubmissionID: "28936",
MetaCreatedDate: "12 Mar 2018",
Program: "Brand Risk Management",
ViewedByInvestigator: "Yes",
}];
const nameMap = {
SubmissionID: 'SubmissionIdentifier',
MetaCreatedDate: 'CreationDate',
Program: 'ProgramName',
ViewedByInvestigator: 'Viewed'
}
function renameKeys(obj, map) {
const newObj = {};
for (let key in obj) {
newObj[map[key]] = obj[key];
}
return newObj;
}
console.log(obj.map(item => renameKeys(item, nameMap)));
I'd also note that if you happen to be using the lodash library, you can also use it's _.mapKeys method to do this.
I'm gonna use .map() function to change the key names. The input data will remain unchanged. Hope this helps.
var obj = [{
SubmissionID: "28935",
MetaCreatedDate: "12 Mar 2018",
Program: "Brand Risk Management",
ViewedByInvestigator: "No",
},
{
SubmissionID: "28936",
MetaCreatedDate: "12 Mar 2018",
Program: "Brand Risk Management",
ViewedByInvestigator: "Yes",
}]
var output = obj.map(element => ({
SubmissionIdentifier: element.SubmissionID,
CreationDate: element.MetaCreatedDate,
ProgramName: element.Program,
Viewed: element.ViewedByInvestigator
}));

Generate a JSON file from keyless list in Python

I've been doing some web-scraping recently and ultimately fetched the data I wanted. However, there is no sense of organization since it's only a simple list in Python. It contains the meeting type (either LE/DI/SE), days, time, professor's name (edited for privacy), among some other values.
["LE", "A00", "MWF", "10:00a-10:50a", "MLK", "AUD", "Smith, John", "976539", "DI", "A01", "F", "5:00p-5:50p", "MLK", "AUD", "Smith, John", "FULL Waitlist(25)", "216", "FI", "03/17/2018", "S", "8:00a-10:59a", "TBA", "TBA", "LE", "B00", "MWF", "1:00p-1:50p", "WLH", "2005", "Smith, John", "927471", "DI", "B01", "F", "6:00p-6:50p", "MLK", "AUD", "Smith, John", "FULL Waitlist(32)", "200", "FI", "03/17/2018", "S", "8:00a-10:59a", "TBA", "TBA"]
As you can see, it's an ugly list. My goal is to make it something like this:
{
"MATH101": {
"LE": {
sectionCode: 'A00',
days: 'MFW',
times: '10:00a-10:50am',
building: 'MLK',
room: 'AUD',
instructor: 'Smith, John',
"DI": {
sectionCode: 'A01',
days: 'F',
times: '5:00-5:50pm',
building: 'MLK',
room: 'AUD',
instructor: 'Smith, John',
availableSeats: 'FULL Waitlist(25)',
capacity: '216'
}
},
"LE": {
sectionCode: 'B00',
days: 'MFW',
times: '1:00a-1:50pm',
building: 'MLK',
room: 'AUD',
instructor: 'Smith, John',
"DI": {
sectionCode: 'B01',
days: 'F',
times: '6:00-6:50pm',
building: 'MLK',
room: 'AUD',
instructor: 'Smith, John',
availableSeats: 'FULL Waitlist(32)',
capacity: '200'
}
}
}
}
There is a discussion per lecture section, thus there are two lecture times and two discussions that pertain to each lecture. I don't know if there is a better schema to store this data, but I could only come up with this.
I thought iterating through the list and saving values starting after the "LE" or "DI" strings into the ordered way that I established above, but I don't see how that would help me create the json file without each key.
I'm new to all this, and I haven't been able to find a solution. Tried converting into dictionary but it doesn't meet my needs. A lot of data is also repeated, such as the professor's name, but there won't always be one professor, nor two lectures/discussions. I plan to do this with all the courses available, so this just gets more and more complicated...
Hopefully someone is able to help out, thank you!

Javascript collection find values with Lodash

I have an array shown as below. I want to know which values inside departure and arrival fields.
Array :
var data = {
"origin": "Antalya",
"destination": "IST",
"flights": [{
"provider": "thy",
"time": "2017-07-07 10:30",
"legs": [{
"departure": "AYT",
"arrival": "IST"
}]
},{
"provider": "thy",
"time": "2017-07-07 14:30",
"legs": [{
"departure": "AYT",
"arrival": "ESB"
},{
"departure": "ESB",
"arrival": "IST"
}]
},{
"provider": "pegasus",
"time": "2017-07-07 06:30",
"legs": [{
"departure": "AYT",
"arrival": "ADB"
},{
"departure": "ADB",
"arrival": "IST"
}]
}]
};
I want to new array like this :
["AYT","IST","ESB","ADB"]
How can i handle it using lodash?
Here's a solution using lodash:
let result = _(data.flights)
.flatMap('legs')
.flatMap(_.values)
.uniq()
.value();
First we get a flattened array of legs, transform that into a flattened array of the values of the properties of each leg, before finally getting the unique values.
Well loop through your data and create a string array, and then use the uniq function, like:
var data = {"origin":"Antalya","destination":"IST","flights":[{"provider":"thy","time":"2017-07-07 10:30","legs":[{"departure":"AYT","arrival":"IST"}]},{"provider":"thy","time":"2017-07-07 14:30","legs":[{"departure":"AYT","arrival":"ESB"},{"departure":"ESB","arrival":"IST"}]},{"provider":"pegasus","time":"2017-07-07 06:30","legs":[{"departure":"AYT","arrival":"ADB"},{"departure":"ADB","arrival":"IST"}]}]};
var legs = [];
_.each(data.flights, flight => {
_.each(flight.legs, leg => {
legs.push(leg.departure);
legs.push(leg.arrival);
});
});
console.log(_.uniq(legs));
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>

Categories

Resources