Related
I am trying to make a car year, make, model dependable values form. My arrays are in the following format. For the selected year and selected make, i want to populate the corresponding model value.
I have put unique year and make into separate another array. How will i achieve the intended result?
var car_arrays = [
{
id: 1,
year: 1909,
make: "Ford",
model: "Model T",
},
{
id: 2,
year: 1926,
make: "Chrysler",
model: "Imperial",
},
{
id: 3,
year: 1948,
make: "Citroën",
model: "2CV",
},
{
id: 4,
year: 1950,
make: "Hillman",
model: "Minx Magnificent",
},
{
id: 5,
year: 1953,
make: "Chevrolet",
model: "Corvette",
},
{
id: 7,
year: 1954,
make: "Cadillac",
model: "Fleetwood",
},
{
id: 6,
year: 1954,
make: "Chevrolet",
model: "Corvette",
},
{
id: 8,
year: 1955,
make: "Chevrolet",
model: "Corvette",
},
{
id: 9,
year: 1955,
make: "Ford",
model: "Thunderbird",
},
{
id: 10,
year: 1956,
make: "Chevrolet",
model: "Corvette",
},
{
id: 12,
year: 1957,
make: "BMW",
model: "600",
},
{
id: 11,
year: 1957,
make: "Chevrolet",
model: "Corvette",
},
{
id: 14,
year: 1958,
make: "BMW",
model: "600",
},
{
id: 13,
year: 1958,
make: "Chevrolet",
model: "Corvette",
},
{
id: 15,
year: 1958,
make: "Ford",
model: "Thunderbird",
},
{
id: 16,
year: 1959,
make: "Austin",
model: "Mini",
},
{
id: 18,
year: 1959,
make: "BMW",
model: "600",
},
{
id: 17,
year: 1959,
make: "Chevrolet",
model: "Corvette",
},
{
id: 19,
year: 1960,
make: "Chevrolet",
model: "Corvair",
},
{
id: 20,
year: 1960,
make: "Chevrolet",
model: "Corvette",
},
{
id: 22,
year: 1960,
make: "Fairthorpe",
model: "Rockette",
},
{
id: 21,
year: 1960,
make: "Fillmore",
model: "Fillmore",
},
{
id: 23,
year: 1961,
make: "Austin",
model: "Mini Cooper",
},
{
id: 26,
year: 1961,
make: "Chevrolet",
model: "Corvette",
},
{
id: 25,
year: 1961,
make: "Pontiac",
model: "Tempest",
},
{
id: 24,
year: 1961,
make: "Studebaker",
model: "Avanti",
},
{
id: 30,
year: 1962,
make: "Buick",
model: "Special",
},
{
id: 28,
year: 1962,
make: "Chevrolet",
model: "Corvette",
},
{
id: 27,
year: 1962,
make: "Pontiac",
model: "Grand Prix",
},
{
id: 29,
year: 1962,
make: "Studebaker",
model: "Avanti",
},
{
id: 31,
year: 1963,
make: "Austin",
model: "Mini",
},
{
id: 32,
year: 1963,
make: "Austin",
model: "Mini Cooper S",
},
{
id: 37,
year: 1963,
make: "Chevrolet",
model: "Corvair 500",
},
{
id: 38,
year: 1963,
make: "Chevrolet",
model: "Corvette",
},
{
id: 34,
year: 1963,
make: "Ford",
model: "E-Series",
},
{
id: 36,
year: 1963,
make: "Pontiac",
model: "Grand Prix",
},
{
id: 33,
year: 1963,
make: "Rambler",
model: "Classic",
},];
function getYear() {
var makeid = document.getElementById("makeid");
var select, option;
select = document.getElementById("yearid");
for (let y in year) {
option = document.createElement("option");
option.value = option.text = year[y];
select.add(option);
}
var selectyear = document.getElementById("yearid");
makeid.removeAttribute("disabled");
}
function getMake() {
var makeid, yearid, option;
makeidselect = document.getElementById("makeid");
yearidselect = document.getElementById("yearid");
for (let y in year) {
option = document.createElement("option");
option.value = option.text = year[y];
yearidselect.add(option);
console.log(yearidselect.value);
}
for (let x in make) {
option = document.createElement("option");
option.value = option.text = make[x];
makeidselect.add(option);
console.log(makeidselect.value);
}
var year = [
1909, 1926, 1948, 1950, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961,
1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974,
1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987,
1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013,
2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021,
];
var make = [
"Ford",
"Chrysler",
"Citroën",
"Hillman",
"Chevrolet",
"Cadillac",
"BMW",
"Austin",
"Fairthorpe",
"Fillmore",
"Pontiac",
"Studebaker",
"Buick",
"Rambler",
"Plymouth",
"Volkswagen",
"Jensen",
"Oldsmobile",
"Mercury",
"Dodge",
"Shelby",
"Porsche",
"Toyota",
"Mercedes-Benz",
"MG",
"Nissan",
"Honda",
"Mazda",
"Renault",
"Audi",
"Lincoln",
"Lotus",
"Maserati",
"Mitsubishi",
"Saab",
"Subaru",
"Suzuki",
"Lamborghini",
"Merkur",
"Land Rover",
"Acura",
"Lexus",
"Eagle",
"Alfa Romeo",
"Daihatsu",
"Geo",
"GMC",
"Hyundai",
"Infiniti",
"Isuzu",
"Jaguar",
"Jeep",
"Saturn",
"Volvo",
"HUMMER",
"Kia",
"Holden",
"Corbin",
"Daewoo",
"MINI",
"Maybach",
"Scion",
"Spyker",
"Aston Martin",
"Bentley",
"Panoz",
"Rolls-Royce",
"Spyker Cars",
"Ferrari",
"Hummer",
"Morgan",
"Peugeot",
"Foose",
"Aptera",
"Smart",
"Bugatti",
"Tesla",
"Ram",
"FIAT",
"Fiat",
"McLaren",
"BYD",
"McLaren Automotive",
"Mobility Ventures LLC",
"Pagani",
"Roush Performance",
"smart",
"SRT",
"Genesis",
"Karma",
"Koenigsegg",
"RUF Automobile",
"STI",
"Polestar",
"Kandi",
];
You can do something like this to populate the models dropdown
according to the values of year and make:
var CARS = [{
id: 1,
year: 1909,
make: 'Ford',
model: 'Model T',
},
{
id: 2,
year: 1926,
make: 'Chrysler',
model: 'Imperial',
},
{
id: 3,
year: 1948,
make: 'Citroën',
model: '2CV',
},
{
id: 4,
year: 1950,
make: 'Hillman',
model: 'Minx Magnificent',
},
{
id: 5,
year: 1953,
make: 'Chevrolet',
model: 'Corvette',
},
{
id: 7,
year: 1954,
make: 'Cadillac',
model: 'Fleetwood',
},
{
id: 6,
year: 1954,
make: 'Chevrolet',
model: 'Corvette',
},
{
id: 8,
year: 1955,
make: 'Chevrolet',
model: 'Corvette',
},
{
id: 9,
year: 1955,
make: 'Ford',
model: 'Thunderbird',
},
{
id: 10,
year: 1956,
make: 'Chevrolet',
model: 'Corvette',
},
{
id: 12,
year: 1957,
make: 'BMW',
model: '600',
},
{
id: 11,
year: 1957,
make: 'Chevrolet',
model: 'Corvette',
},
{
id: 14,
year: 1958,
make: 'BMW',
model: '600',
},
{
id: 13,
year: 1958,
make: 'Chevrolet',
model: 'Corvette',
},
{
id: 15,
year: 1958,
make: 'Ford',
model: 'Thunderbird',
},
{
id: 16,
year: 1959,
make: 'Austin',
model: 'Mini',
},
{
id: 18,
year: 1959,
make: 'BMW',
model: '600',
},
{
id: 17,
year: 1959,
make: 'Chevrolet',
model: 'Corvette',
},
{
id: 19,
year: 1960,
make: 'Chevrolet',
model: 'Corvair',
},
{
id: 20,
year: 1960,
make: 'Chevrolet',
model: 'Corvette',
},
{
id: 22,
year: 1960,
make: 'Fairthorpe',
model: 'Rockette',
},
{
id: 21,
year: 1960,
make: 'Fillmore',
model: 'Fillmore',
},
{
id: 23,
year: 1961,
make: 'Austin',
model: 'Mini Cooper',
},
{
id: 26,
year: 1961,
make: 'Chevrolet',
model: 'Corvette',
},
{
id: 25,
year: 1961,
make: 'Pontiac',
model: 'Tempest',
},
{
id: 24,
year: 1961,
make: 'Studebaker',
model: 'Avanti',
},
{
id: 30,
year: 1962,
make: 'Buick',
model: 'Special',
},
{
id: 28,
year: 1962,
make: 'Chevrolet',
model: 'Corvette',
},
{
id: 27,
year: 1962,
make: 'Pontiac',
model: 'Grand Prix',
},
{
id: 29,
year: 1962,
make: 'Studebaker',
model: 'Avanti',
},
{
id: 31,
year: 1963,
make: 'Austin',
model: 'Mini',
},
{
id: 32,
year: 1963,
make: 'Austin',
model: 'Mini Cooper S',
},
{
id: 37,
year: 1963,
make: 'Chevrolet',
model: 'Corvair 500',
},
{
id: 38,
year: 1963,
make: 'Chevrolet',
model: 'Corvette',
},
{
id: 34,
year: 1963,
make: 'Ford',
model: 'E-Series',
},
{
id: 36,
year: 1963,
make: 'Pontiac',
model: 'Grand Prix',
},
{
id: 33,
year: 1963,
make: 'Rambler',
model: 'Classic',
},
]
const YEARS = [
1909, 1926, 1948, 1950, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961,
1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974,
1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987,
1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013,
2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021,
]
const MAKES = [
'Ford',
'Chrysler',
'Citroën',
'Hillman',
'Chevrolet',
'Cadillac',
'BMW',
'Austin',
'Fairthorpe',
'Fillmore',
'Pontiac',
'Studebaker',
'Buick',
'Rambler',
'Plymouth',
'Volkswagen',
'Jensen',
'Oldsmobile',
'Mercury',
'Dodge',
'Shelby',
'Porsche',
'Toyota',
'Mercedes-Benz',
'MG',
'Nissan',
'Honda',
'Mazda',
'Renault',
'Audi',
'Lincoln',
'Lotus',
'Maserati',
'Mitsubishi',
'Saab',
'Subaru',
'Suzuki',
'Lamborghini',
'Merkur',
'Land Rover',
'Acura',
'Lexus',
'Eagle',
'Alfa Romeo',
'Daihatsu',
'Geo',
'GMC',
'Hyundai',
'Infiniti',
'Isuzu',
'Jaguar',
'Jeep',
'Saturn',
'Volvo',
'HUMMER',
'Kia',
'Holden',
'Corbin',
'Daewoo',
'MINI',
'Maybach',
'Scion',
'Spyker',
'Aston Martin',
'Bentley',
'Panoz',
'Rolls-Royce',
'Spyker Cars',
'Ferrari',
'Hummer',
'Morgan',
'Peugeot',
'Foose',
'Aptera',
'Smart',
'Bugatti',
'Tesla',
'Ram',
'FIAT',
'Fiat',
'McLaren',
'BYD',
'McLaren Automotive',
'Mobility Ventures LLC',
'Pagani',
'Roush Performance',
'smart',
'SRT',
'Genesis',
'Karma',
'Koenigsegg',
'RUF Automobile',
'STI',
'Polestar',
'Kandi',
]
MAKES.sort()
const yearSelection = document.getElementById('year')
const makeSelection = document.getElementById('make')
const modelSelection = document.getElementById('model')
const displayedCars = document.getElementById('cars')
for (let year of YEARS) {
const option = document.createElement('option')
option.textContent = year
option.value = year
yearSelection.appendChild(option)
}
for (let make of MAKES) {
const option = document.createElement('option')
option.textContent = make
option.value = make
makeSelection.appendChild(option)
}
const models = []
for (let car of CARS) {
const model = car.model
if (models.findIndex(m => m == model) == -1) {
const option = document.createElement('option')
option.className = 'car-model'
models.push(model)
option.textContent = model
option.value = model
modelSelection.appendChild(option)
}
}
const modelOptions = Object.values(document.querySelectorAll('.car-model'))
function populateModels() {
const selectedYear = yearSelection.value
const selectedMake = makeSelection.value
const filtered = CARS.filter(
car => car.year == selectedYear && car.make == selectedMake
)
for (let option of modelOptions) {
if (filtered.find(v => v.model == option.value)) {
option.hidden = false
} else {
option.hidden = true
}
}
if (filtered.length > 0) {
modelSelection.value = filtered[0].model
} else {
modelSelection.value = 'none'
}
}
populateModels()
yearSelection.onchange = () => populateModels()
makeSelection.onchange = () => populateModels()
<!DOCTYPE html>
<html>
<head>
<link rel="shortcut icon" href="#" type="image/x-icon" />
<meta charset="UTF-8" />
</head>
<body>
<select name="" id="year"></select>
<select name="" id="make"></select>
<select name="" id="model">
<option value="none" disabled hidden>No models found</option>
</select>
</body>
<script src="main.js"></script>
</html>
you can loop through the array:
let year = [], let make = [], ....
car_arrays.forEach(car => {
year.push(car.year)
make.push(car.make) ...
})
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I'm receiving data from an Angular service as follow:
{
"data": [
{
"country": "Germany",
"iso": "de",
"city": "Berlin",
"zone": "2",
},
{
"country": "Germany",
"iso": "de",
"city": "Frankfurt",
"zone": "5",
},
{
"country": "USA",
"iso": "us",
"city": "Chicago",
"zone": "18",
},
{
"country": "USA",
"iso": "us",
"city": "New York",
"zone": "16",
},
{
"country": "USA",
"iso": "us",
"city": "San Francisco",
"zone": "54",
}
}
I would like to transform these data so I can use the AutoComplete PrimeNG widget which require the following data format as input:
groupedByCountry = [
{
label: 'Germany', value: 'de',
items: [
{label: 'Berlin', value: '2'},
{label: 'Frankfurt', value: '5'}
]
},
{
label: 'USA', value: 'us',
items: [
{label: 'Chicago', value: '18'},
{label: 'New York', value: '16'},
{label: 'San Francisco', value: '54'}
]
}
];
I'm not doing JavaScript on a daily basis and haven't be able to do this transformation so far. If someone could assist it would be appreciated
this should work:
let input = JSON.parse(`[
{
"country": "Germany",
"iso": "de",
"city": "Berlin",
"zone": "2"
},
{
"country": "Germany",
"iso": "de",
"city": "Frankfurt",
"zone": "5"
},
{
"country": "USA",
"iso": "us",
"city": "Chicago",
"zone": "18"
},
{
"country": "USA",
"iso": "us",
"city": "New York",
"zone": "16"
},
{
"country": "USA",
"iso": "us",
"city": "San Francisco",
"zone": "54"
}
]`)
const res = Object.values(input.reduce((acc, el)=>{
if(!acc[el.country]){
acc[el.country] = {
label: el.country,
value: el.iso,
items: [
{
label: el.city,
value: el.zone
}
]
}
} else {
acc[el.country].items.push({
label: el.city,
value: el.zone
})
}
return acc;
}, {}))
console.log(res)
in few words:
create a Map like country -> object
for each element of the array, if in the map that country already exists, then just push the new element, otherwise create it
I have a json file in the following format:
const data = [
{category: "A", country: "UK", name: "United Kingdom", country_id: "01", 2015: 5, 2016: 56, 2017: 10},
{category: "B", country: "UK", name: "United Kingdom", country_id: "01", 2015: 4, 2016: 10, 2017: 10},
{category: "C", country: "UK", name: "United Kingdom", country_id: "01", 2015: 10, 2016: 7, 2017: 45},
{category: "A", country: "PO", name: "Poland", country_id: "02", 2015: 9, 2016: 14, 2017: 10},
{category: "B", country: "PO", name: "Poland", country_id: "02", 2015: 10, 2016: 40, 2017: 0},
{category: "C", country: "PO", name: "Poland", country_id: "02", 2015: 60, 2016: 30, 2017: 74},
{category: "A", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 30, 2016: 20, 2017: 10},
{category: "B", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 15, 2016: 28, 2017: 1},
{category: "C", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 16, 2016: 10, 2017: 2}
]
and I want to pivot the data to get the following format:
move 2015, 2016 and 2017 into a property named year
create a, b and c properties from category property values that will contain the different values.
have a line/object per country and year and any other ordinal categories I would like to keep.
const data = [
{country: "UK", name: "United Kingdom", country_id: "01", year: "2015", "a": 5 , "b": 4, "c": 10},
{country: "UK", name: "United Kingdom", country_id: "01", year: "2016", "a": 56 , "b": 10, "c": 7},
{country: "UK", name: "United Kingdom", country_id: "01", year: "2017", "a": 10 , "b": 10, "c": 45},
{country: "PO", name: "Poland", country_id: "02", year: "2015", "a": 9 , "b": 10, "c": 80},
{country: "PO", name: "Poland", country_id: "02", year: "2016", "a": 14 , "b": 40, "c": 30},
{country: "PO", name: "Poland", country_id: "02", year: "2017", "a": 10 , "b": 0, "c": 74},
{country: "CZ", name: "Czech Republic", country_id: "03", year: "2015", "a": 30 , "b": 15, "c": 16},
{country: "CZ", name: "Czech Republic", country_id: "03", year: "2016", "a": 20 , "b": 28, "c": 1},
{country: "CZ", name: "Czech Republic", country_id: "03", year: "2017", "a": 10 , "b": 1, "c": 2}
I tried writing a for loop inside a map method but I am unable to create a, b and c properties.
The rotation is done on the 3 lines commented 'Rotation'
To be able to do this we need to be able to access multiple rows of the original dataset. The strategy here builds us up to be able to do that.
Step 1. Get lists of the unique country_ids, years and categories
There are several ways to do this, and I have shown the easiest to understand method, which is to convert to a Set (which automatically removes duplicates) and then back to an Array for convenience of use.
Step 2. Move from a simple array, into an object
Instead of the rows being simply in sequence 0...8, we now have them in a 3x3 grid, addressible by country and category.
Step 3. Construct the desired output
Now within each country, we can extract all the data for a chosen year, by "plucking" the values for this year from the three different categories in the original data.
const data = [
{category: "A", country: "UK", name: "United Kingdom", country_id: "01", 2015: 5, 2016: 56, 2017: 10},
{category: "B", country: "UK", name: "United Kingdom", country_id: "01", 2015: 4, 2016: 10, 2017: 10},
{category: "C", country: "UK", name: "United Kingdom", country_id: "01", 2015: 10, 2016: 7, 2017: 45},
{category: "A", country: "PO", name: "Poland", country_id: "02", 2015: 9, 2016: 14, 2017: 10},
{category: "B", country: "PO", name: "Poland", country_id: "02", 2015: 10, 2016: 40, 2017: 0},
{category: "C", country: "PO", name: "Poland", country_id: "02", 2015: 60, 2016: 30, 2017: 74},
{category: "A", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 30, 2016: 20, 2017: 10},
{category: "B", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 15, 2016: 28, 2017: 1},
{category: "C", country: "CZ", name: "Czech Republic", country_id: "03", 2015: 16, 2016: 10, 2017: 2}
]
// Step 1. Extract the unique country_id, category Ids and years
const country_ids = Array(...new Set(data.map((x) => x.country_id)));
const categories = Array(...new Set(data.map((x) => x.category)));
const years = ["2015","2016","2017"];
// Step 2. Convert the source data into an object so that you can conveniently read off particular rows, in terms of COUNTRY_ID and CATEGORY
const sourceRows = {};
data.forEach((row) => {
if (!sourceRows[row.country_id]) {
sourceRows[row.country_id] = {};
}
sourceRows[row.country_id][row.category] = row;
});
// You can visualise the output here with this, if you want:
// console.log(sourceRows)
// Step 3. Create destination array, and poke a row into it for each country & year.
const destination = [];
country_ids.forEach((country_id) => {
years.forEach((year) => {
const sourceRow = sourceRows[country_id][categories[0]];
const destRow = {
country_id: country_id,
name: sourceRow.name,
country: sourceRow.country,
year: year,
a: sourceRows[country_id]["A"][year], // Rotation
b: sourceRows[country_id]["B"][year], // Rotation
c: sourceRows[country_id]["C"][year] // Rotation
};
destination.push(destRow);
});
});
console.log(destination);
Not the best solution, but this works. At the and, I made a workaround for the duplicates. You could use ...rest parameter to initialize years array if there will be new data for other years.
let newData = [];
let countries = data.map(({country})=> country)
let categories = data.map(({category})=> category)
let years = [2015,2016,2017];
countries.forEach(country => {
let countryData = data.filter(({country:c}) => c==country);
let yearData = {2015:{},2016:{},2017:{}};
years.forEach(year => {
categories.forEach(category => {
yearData[year][category] = countryData.find(({category:cat}) => cat==category)[year]
})
})
let {name,country_id}= data.find(({country:c}) => c == country);
Object.entries(yearData).forEach(([year,categories]) => {
newData.push({country,name,country_id,year, ...categories})
})
newData = newData.filter((data,i) => i%9<3)
console.log(newData)
})
Having a json file in this format...
data =[
{
key: "london",
values: [
{day: "2020-01-01", city: "london", value: 10},
{day: "2020-01-02", city: "london", value: 20},
{day: "2020-01-03", city: "london", value: 30},
{day: "2020-01-04", city: "london", value: 30},
{day: "2020-01-05", city: "london", value: 30},
{day: "2020-01-06", city: "london", value: 30}
]
},
{
key: "berlin",
values: [
{day: "2020-01-01", city: "berlin", value: 10},
{day: "2020-01-02", city: "berlin", value: 15},
{day: "2020-01-03", city: "berlin", value: 30},
{day: "2020-01-04", city: "berlin", value: 30},
{day: "2020-01-05", city: "berlin", value: 30},
{day: "2020-01-06", city: "berlin", value: 45}
]
},
{
key: "rome",
values: [
{day: "2020-01-01", city: "rome", value: 10},
{day: "2020-01-02", city: "rome", value: 12},
{day: "2020-01-03", city: "rome", value: 6},
{day: "2020-01-04", city: "rome", value: 9},
{day: "2020-01-05", city: "rome", value: 27},
{day: "2020-01-06", city: "rome", value: 36}
]
}]
I was wondering how I can calculate the daily percentage change in the series using javascript. I am expecting to get the following output. If possible, I'd like to remove city in order not to repeat information.
data =[
{
key: "london",
values: [
{day: "2020-01-01", value: 10, perc: 0},
{day: "2020-01-02", value: 20, perc: 1},
{day: "2020-01-03", value: 30, perc: 1},
{day: "2020-01-04", value: 30, perc: 0},
{day: "2020-01-05", value: 30, perc: 0},
{day: "2020-01-06", value: 30, perc: 0}
]
},
{
key: "berlin",
values: [
{day: "2020-01-01", value: 10, perc: 0},
{day: "2020-01-02", value: 15, perc: 0.5},
{day: "2020-01-03", value: 30, perc: 1},
{day: "2020-01-04", value: 30, perc: 0},
{day: "2020-01-05", value: 30, perc: 0},
{day: "2020-01-06", value: 45, perc: 0.5}
]
},
{
key: "rome",
values: [
{day: "2020-01-01", value: 10, perc: 0},
{day: "2020-01-02", value: 12, perc: 0.2},
{day: "2020-01-03", value: 6, perc: -0.5},
{day: "2020-01-04", value: 9, perc: 0.5},
{day: "2020-01-05", value: 27, perc: 2},
{day: "2020-01-06", value: 36, perc: 0.33}
]
}]
Bonus question: What should I do in order to calculate percentage change for a different period of time (every two days, week, etc.) and get an output like the one below? (Showing percentage change every two days)
data =[
{
key: "london",
values: [
{day: "2020-01-01", value: 10, perc: 0},
{day: "2020-01-03", value: 30, perc: 2},
{day: "2020-01-05", value: 30, perc: 0},
]
},
{
key: "berlin",
values: [
{day: "2020-01-01", value: 10, perc: 0},
{day: "2020-01-03", value: 30, perc: 2},
{day: "2020-01-05", value: 30, perc: 0},
]
},
{
key: "rome",
values: [
{day: "2020-01-01", value: 10, perc: 0},
{day: "2020-01-03", value: 6, perc: -0.4},
{day: "2020-01-05", value: 27, perc: 4.5},
]
}]
Here's my take on this situation. It also includes the bonus question.
P.S.: This is my first stackoverflow post, if you have any questions please ask!
// Your input data
const data = [
{
key: "london",
values: [
{day: "2020-01-01", city: "london", value: 10},
{day: "2020-01-02", city: "london", value: 20},
{day: "2020-01-03", city: "london", value: 30},
{day: "2020-01-04", city: "london", value: 30},
{day: "2020-01-05", city: "london", value: 30},
{day: "2020-01-06", city: "london", value: 30}
]
},
{
key: "berlin",
values: [
{day: "2020-01-01", city: "berlin", value: 10},
{day: "2020-01-02", city: "berlin", value: 15},
{day: "2020-01-03", city: "berlin", value: 30},
{day: "2020-01-04", city: "berlin", value: 30},
{day: "2020-01-05", city: "berlin", value: 30},
{day: "2020-01-06", city: "berlin", value: 45}
]
},
{
key: "rome",
values: [
{day: "2020-01-01", city: "rome", value: 10},
{day: "2020-01-02", city: "rome", value: 12},
{day: "2020-01-03", city: "rome", value: 6},
{day: "2020-01-04", city: "rome", value: 9},
{day: "2020-01-05", city: "rome", value: 27},
{day: "2020-01-06", city: "rome", value: 36}
]
}];
// The parsed output data
const parsedData = data.map((obj) => {
// Maps the object values to calculate the percentage
return {...obj, values: obj.values.map((value, i) => {
// Delete the "city" key
delete value['city'];
// Can't calculate the percentage on the first element
if (i == 0)
return { ...value, perc: 0 };
// Get the current & previous day/value
const currentValue = value.value;
const currentDay = new Date(value.day);
const previousValue = obj.values[i-1].value;
const previousDay = new Date(obj.values[i-1].day);
// Calculate the days between the previous and current entry
const dayTimeDiff = Math.abs(currentDay - previousDay);
const dayDiff = Math.ceil(dayTimeDiff / (1000 * 60 * 60 * 24));
// Calculate the precentage = (current - previous) / previous
const percentDiff = currentValue - previousValue / previousValue / dayDiff;
return { ...value, perc: percentDiff };
})}
});
console.log(parsedData);
For the first part, you can manipulate each value inside values array:
const data = [
{
key: "london",
values: [
{day: "2020-01-01", city: "london", value: 10},
{day: "2020-01-02", city: "london", value: 20},
{day: "2020-01-03", city: "london", value: 30},
{day: "2020-01-04", city: "london", value: 30},
{day: "2020-01-05", city: "london", value: 30},
{day: "2020-01-06", city: "london", value: 30}
]
},
{
key: "berlin",
values: [
{day: "2020-01-01", city: "berlin", value: 10},
{day: "2020-01-02", city: "berlin", value: 15},
{day: "2020-01-03", city: "berlin", value: 30},
{day: "2020-01-04", city: "berlin", value: 30},
{day: "2020-01-05", city: "berlin", value: 30},
{day: "2020-01-06", city: "berlin", value: 45}
]
},
{
key: "rome",
values: [
{day: "2020-01-01", city: "rome", value: 10},
{day: "2020-01-02", city: "rome", value: 12},
{day: "2020-01-03", city: "rome", value: 6},
{day: "2020-01-04", city: "rome", value: 9},
{day: "2020-01-05", city: "rome", value: 27},
{day: "2020-01-06", city: "rome", value: 36}
]
}]
const newData = data.map((info) => {
const n = info.values.length;
const valuesCopy = info.values.map((info) => info.value);
for (let i = 0; i < n; i++) {
const currentValue = valuesCopy[i];
const previousValue = valuesCopy[i - 1];
// calculate the percentage
const percentage = (currentValue - previousValue) / previousValue;
// percentage is NaN return 0
// percentage is < 1, return 2 decimal places
// otherwise return percentage
info.values[i].value = !percentage ? 0 : percentage < 1 ? percentage.toFixed(2) : percentage;
}
return info;
})
console.log(JSON.stringify(newData, null, 2));
Example using simple for loops + comments:
const data =[
{
key: "london",
values: [
{day: "2020-01-01", city: "london", value: 10},
{day: "2020-01-02", city: "london", value: 20},
{day: "2020-01-03", city: "london", value: 30},
{day: "2020-01-04", city: "london", value: 30},
{day: "2020-01-05", city: "london", value: 30},
{day: "2020-01-06", city: "london", value: 30}
]
},
{
key: "berlin",
values: [
{day: "2020-01-01", city: "berlin", value: 10},
{day: "2020-01-02", city: "berlin", value: 15},
{day: "2020-01-03", city: "berlin", value: 30},
{day: "2020-01-04", city: "berlin", value: 30},
{day: "2020-01-05", city: "berlin", value: 30},
{day: "2020-01-06", city: "berlin", value: 45}
]
},
{
key: "rome",
values: [
{day: "2020-01-01", city: "rome", value: 10},
{day: "2020-01-02", city: "rome", value: 12},
{day: "2020-01-03", city: "rome", value: 6},
{day: "2020-01-04", city: "rome", value: 9},
{day: "2020-01-05", city: "rome", value: 27},
{day: "2020-01-06", city: "rome", value: 36}
]
}
];
// Define resulting array
const results = [];
// Loop data
for(let i = 0; i < data.length; i++) {
// Set city object
const city = {
key: data[i].key,
values: []
};
// Set shorcut to values
const dVal = data[i].values
// Loop values in city entry
for(let i = 0; i < dVal.length; i++) {
// Set previous value or current if it is first cycle
const prev = (i !== 0) ? dVal[i-1].value : dVal[i].value;
// Set current value
const cur = dVal[i].value;
// Calculate percentage
let percDiff = (cur - prev) / prev;
// Fancy result as you need
percDiff = parseFloat(percDiff.toFixed(2));
// Push to city object
city.values.push({
day: dVal[i].day,
value: dVal[i].value,
perc: percDiff
});
}
// Push city object to resulting array
results.push(city);
}
// Log
console.log(results);
Answer on your second question, if I get it right, is simple - remove day entries that you don't need from array and pass resulting array to the same function. It calculates difference between entries, doesn't matter it is day or week
I have an array of objects and I need to trim the created_at value and return the full array of objects descending by most recent created_at value.
I can perform the sort as desired but my code only returns the create_at value, not the entire object in that sorted order
How do I alter the map function so that I don't isolate the created_at value?
var notes = [
{
country: "Angola",
denomination: 50,
currency: "Kwanzas",
issue_date: 2012,
created_at: "2017-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Rwanda",
denomination: 5000,
currency: "Francs",
issue_date: 2009,
created_at: "2008-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Serbia",
denomination: 50,
currency: "Dinara",
issue_date: 2011,
created_at: "2015-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Moldova",
denomination: 20,
currency: "Lei",
issue_date: 2013,
created_at: "2009-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Liberia",
denomination: 10,
currency: "Dollars",
issue_date: 2010,
created_at: "1998-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Kazakhstan",
denomination: 500,
currency: "Tenge",
issue_date: 2019,
created_at: "2001-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
}
]
var dateMap = notes.map(note => note.created_at.substring(0,10)).sort().reverse()
The correct result would be:
dateMap = [
{
country: "Angola",
denomination: 50,
currency: "Kwanzas",
issue_date: 2012,
created_at: "2017-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Serbia",
denomination: 50,
currency: "Dinara",
issue_date: 2011,
created_at: "2015-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Moldova",
denomination: 20,
currency: "Lei",
issue_date: 2013,
created_at: "2009-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Rwanda",
denomination: 5000,
currency: "Francs",
issue_date: 2009,
created_at: "2008-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Kazakhstan",
denomination: 500,
currency: "Tenge",
issue_date: 2019,
created_at: "2001-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Liberia",
denomination: 10,
currency: "Dollars",
issue_date: 2010,
created_at: "1998-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
]
Provide your own comparator:
const byDate = note => note.created_at.substring(0,10);
notes.sort((a, b) => byDate(b).localeCompare(byDate(a)));
Seems all you are needing is a sort which you can do by comparing the property values in sort function
notes.sort((a, b) => b.created_at.localeCompare(a.created_at))
console.log(notes)
<script>
var notes = [{
country: "Angola",
denomination: 50,
currency: "Kwanzas",
issue_date: 2012,
created_at: "2017-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Rwanda",
denomination: 5000,
currency: "Francs",
issue_date: 2009,
created_at: "2008-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Serbia",
denomination: 50,
currency: "Dinara",
issue_date: 2011,
created_at: "2015-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Moldova",
denomination: 20,
currency: "Lei",
issue_date: 2013,
created_at: "2009-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Liberia",
denomination: 10,
currency: "Dollars",
issue_date: 2010,
created_at: "1998-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
},
{
country: "Kazakhstan",
denomination: 500,
currency: "Tenge",
issue_date: 2019,
created_at: "2001-07-20T18:41:15.000Z",
updated_at: "2019-07-20T18:41:15.000Z"
}
]
</script>