How to loop values in an array with similar values but distinctively? - javascript

var items =[
{ID:1,day:'mon',val1:10,val2:20,val3:10},
{ID:2,day:'mon',val1:11,val2:70,val3:55},
{ID:3,day:'mon',val1:15,val2:27,val3:37},
{ID:4,day:'teu',val1:9,val2:17,val3:11}
]
var workDays = ['mon','teu']
I need to loop through the item array above.. and append the data elsewhere in the following form:
--loop block starts--
Day:// from workDays
Values:// from item array
--loop block ends---
Final result Should be something like
Day:'mon'
Values:10,20,10...(display all values corresponding to 'mon' in item array
How do i go about that?

You can use ES6 destructuring and easily achieve what you want:
var items = [{
ID: 1,
day: 'mon',
val1: 10,
val2: 20,
val3: 10
},
{
ID: 2,
day: 'mon',
val1: 11,
val2: 70,
val3: 55
}, {
ID: 3,
day: 'mon',
val1: 15,
val2: 27,
val3: 37
}, {
ID: 4,
day: 'teu',
val1: 9,
val2: 17,
val3: 11
}
]
var workDays = ['mon', 'teu']
const result = workDays.map(day => {
const dayItems = items.filter(item => item.day === day);
const values = dayItems.reduce((a, {
val1,
val2,
val3
}) => [...a, val1, val2, val3], []);
return {
Day: day,
Values: values,
};
});
console.log(result);

You could achieve it using map, filter and flat. something like this
const items = [
{"ID": 1, "day": "mon", "val1": 10, "val2": 20, "val3": 10},
{"ID": 2, "day": "mon", "val1": 11, "val2": 70, "val3": 55},
{"ID": 3, "day": "mon", "val1": 15, "val2": 27, "val3": 37},
{"ID": 4, "day": "teu", "val1": 9, "val2": 17, "val3": 11}
];
const workDays = ["mon", "teu"];
const result = workDays.map(day => {
return {
"Day": day,
"values": items.filter(item => item.day === day).map(i => {
return [i.val1, i.val2, i.val3];
}).flat()
};
});
console.log(result);

Related

Calculate Percentage in Java Script and Output Result

I am trying to use below Script to Get the Average of Disconnect Devices .The results are output in group for each Test Customer .
var dataObject = [{
"Customer_Nbr": "13",
"Customer_Name": "Test1",
"Connected_Devices": 7,
"Disconnected_Devices": 1,
"Total_Devices": 8
},
{
"Customer_Nbr": "13",
"Customer_Name": "Test1",
"Connected_Devices": 6,
"Disconnected_Devices": 2,
"Total_Devices": 8
},
{
"Customer_Nbr": "12",
"Customer_Name": "Test3",
"Connected_Devices": 8,
"Disconnected_Devices": 2,
"Total_Devices": 10
}
];
groups = dataObject.reduce(function(r, o) {
var k = o.Customer_Nbr + o.Customer_Name;
if (r[k]) {
if (o.Disconnected_Devices)
(r[k].Disconnected_Devices += o.Disconnected_Devices) && ++r[k].Average;
} else {
r[k] = o;
r[k].Average = 1; // taking 'Average' attribute as an items counter(on the first phase)
}
return r;
}, {});
// getting "average of Points"
var result = Object.keys(groups).map(function(k) {
groups[k].Average = Math.round(groups[k].Disconnected_Devices / groups[k].Average);
return groups[k];
});
console.log(result)
Now I also want grouped output to have a percentage calculation which would be result/Total_Devices * 100 .
Output Should be Something like Assuming Total_Devices Count is constant in Input data -
[
{
Customer_Nbr: '13',
Customer_Name: 'Test1',
Connected_Devices: 7,
Disconnected_Devices: 3,
Total_Devices: 8,
Average: 2
Percent: 25
},
{
Customer_Nbr: '12',
Customer_Name: 'Test3',
Connected_Devices: 8,
Disconnected_Devices: 2,
Total_Devices: 10,
Average: 2
Percent: 20
}
]
Something like this maybe?
var dataObject = [
{
Customer_Nbr: "13",
Customer_Name: "Test1",
Connected_Devices: 7,
Disconnected_Devices: 1,
Total_Devices: 8,
},
{
Customer_Nbr: "13",
Customer_Name: "Test1",
Connected_Devices: 6,
Disconnected_Devices: 2,
Total_Devices: 8,
},
{
Customer_Nbr: "12",
Customer_Name: "Test3",
Connected_Devices: 8,
Disconnected_Devices: 2,
Total_Devices: 10,
},
];
groups = dataObject.reduce(function (r, o) {
var k = o.Customer_Nbr + o.Customer_Name;
if (r[k]) {
if (o.Disconnected_Devices)
(r[k].Disconnected_Devices += o.Disconnected_Devices) && ++r[k].Average;
} else {
r[k] = o;
r[k].Average = 1; // taking 'Average' attribute as an items counter(on the first phase)
}
return r;
}, {});
// getting "average of Points"
var result = Object.keys(groups).map(function (k) {
groups[k].Average = Math.round(
groups[k].Disconnected_Devices / groups[k].Average
);
groups[k].percentage = (groups[k].Average/groups[k].Total_Devices) * 100;
return groups[k];
});
console.log(result);

Filter Dynamic keys based on input

I have an array and I need to filter out keys based on an input string. Only OLD_VAL is static, the rest are dynamic. I tried using the variable but it is not bringing that key
let input = VKORG,VTWEG,MATNR;
let arr = [
{
VKORG: 1100,
VTWEG: 10,
MATNR: 12,
RATE: 0.01,
VALUE: 1,
OLD_VAL: 12,
},
{
VKORG: 2100,
VTWEG: 99,
MATNR: 13,
RATE: 0.11,
VALUE: 11,
OLD_VAL: 12,
},
];
Output:
[
{
VKORG: "1100",
VTWEG: 10,
MATNR: "12",
OLD_VAL: 12,
},
{
VKORG: "2100",
VTWEG: 99,
MATNR: "13",
OLD_VAL: 12,
},
];
Code tried
let filterResults = results.map(({ OLD_VAL,input }) => ({ OLD_VAL, input }))
Assuming input is an array of strings, you can use Object.entries and create an object at each iteration consisting of the key-value pairs where keys are obtained from the input.
const input = ['VKORG', 'VTWEG', 'MATNR']
const arr = [{
VKORG: 1100,
VTWEG: 10,
MATNR: 12,
RATE: 0.01,
VALUE: 1,
OLD_VAL: 12,
},
{
VKORG: 2100,
VTWEG: 99,
MATNR: 13,
RATE: 0.11,
VALUE: 11,
OLD_VAL: 12,
}
]
const result = arr.map(el => Object.fromEntries(input.map(key => [key, el[key]]).concat([['OLD_VAL', el.OLD_VAL]])));
console.log(result);
If the input isn't an array of strings but is a string('VKORG,VTWEG,MATNR') then you can split it and use the above logic.
const input = 'VKORG,VTWEG,MATNR';
const inputArr = input.split(',');
const arr = [{
VKORG: 1100,
VTWEG: 10,
MATNR: 12,
RATE: 0.01,
VALUE: 1,
OLD_VAL: 12,
},
{
VKORG: 2100,
VTWEG: 99,
MATNR: 13,
RATE: 0.11,
VALUE: 11,
OLD_VAL: 12,
}
]
// using a spread operator instead of concat
const result = arr.map(el => Object.fromEntries([
...inputArr.map(key => [key, el[key]]), ['OLD_VAL', el.OLD_VAL]
]));
console.log(result);
You can do this with either way :
Good old for loop
const newArr = [];
for(let obj of arr) {
let newObj = {}
for(let key of input) {
console.log(key)
newObj[key] = obj[key]
}
newArr.push(newObj);
}
Or using map and reduce methods of the Array interface:
arr.map( e => input.reduce((acc, key) => {
acc[key] = e[key];
return acc;
},{}))
PS: dont forget that object keys are strings so your input variable should be :
const input = ['VKORG', 'VTWEG', 'MATNR']

Assigning value 0 to unmatched item in two different array

The following code has two different array with a common field (key). I am using that key to combine these array and result a new array.
const listA = [
{"id": 1, "name":"Rohit"},
{"id": 2, "name":"Raj"},
{"id": 3, "name":"Maggie"}
]
const listB = [
{"id": 1, "count": 30},
{"id": 2, "count": 20}
]
const merge = listA.map(a => ({
...listB.find((b) => (b.id === a.id) && b), ...a
}))
console.log(merge)
How can I achieve 'count' : 0 for unmatched items from ListA ? I meant how can I achive following output:
[
{
"id": 1,
"count": 30,
"name": "Rohit"
},
{
"id": 2,
"count": 20,
"name": "Raj"
},
{
"id": 3,
"count": 0
"name": "Maggie",
}
]
Either you define count before the spread operator override (or not) the key.
const listA = [{
id: 1,
name: 'Rohit',
},
{
id: 2,
name: 'Raj',
},
{
id: 3,
name: 'Maggie',
},
];
const listB = [{
id: 1,
count: 30,
},
{
id: 2,
count: 20,
},
];
const merge = listA.map(a => ({
count: 0,
...listB.find(b => (b.id === a.id) && b),
...a,
}));
console.log(merge);
Either you handle the case where find doesn't find anything :
const listA = [{
id: 1,
name: 'Rohit',
},
{
id: 2,
name: 'Raj',
},
{
id: 3,
name: 'Maggie',
},
];
const listB = [{
id: 1,
count: 30,
},
{
id: 2,
count: 20,
},
];
const merge = listA.map(a => ({
...(listB.find(b => (b.id === a.id) && b) || {
count: 0,
}),
...a,
}));
console.log(merge);
You're almost there
if ...listB.find((b) => (b.id === a.id) && b) is undefined, you can use ...listB.find((b) => (b.id === a.id) && b) || { "count":0 } :
const listA = [
{"id": 1, "name":"Rohit"},
{"id": 2, "name":"Raj"},
{"id": 3, "name":"Maggie"}
]
const listB = [
{"id": 1, "count": 30},
{"id": 2, "count": 20}
]
const merge = listA.map(a => ({
...listB.find((b) => (b.id === a.id) && b) || { "count":0 }, ...a
}))
console.log(merge)
You can use below utility.
const listA = [
{"id": 1, "name":"Rohit"},
{"id": 2, "name":"Raj"},
{"id": 3, "name":"Maggie"}
]
const listB = [
{"id": 1, "count": 30},
{"id": 2, "count": 20}
]
const result = listA.map(objA => {
const foundObj = listB.find(objB => objB.id === objA.id) || {count: 0}
return {...objA, ...foundObj}
})
console.log(result)
Hope this helps
A possible solution would be
const listA = [
{"id": 1, "name":"Rohit"},
{"id": 2, "name":"Raj"},
{"id": 3, "name":"Maggie"}
]
const listB = [
{"id": 1, "count": 30},
{"id": 2, "count": 20}
]
const merge = listA.map(a => ({
...listB.find((b) => (b.id === a.id) && b) || {count: 0 }, ...a
}))
console.log(merge)
Just use a default value for count, if you don't find a matching item in listB;
const mapped = listA.map(({id, name}) => {
const {count} = {count: 0, ...listB.find(({id: _id}) => id === _id)}
return {id, name, count}
})
console.log (mapped);
<script>
const listA = [
{"id": 1, "name":"Rohit"},
{"id": 2, "name":"Raj"},
{"id": 3, "name":"Maggie"}
]
const listB = [
{"id": 1, "count": 30},
{"id": 2, "count": 20}
]
</script>

Removing dynamic keys from array of objects

This previous question comes closest to what I am curious of. I've tried several variations of indexOf() and filter() to no success
I have an arrays of objects (exampleDat):
[{id:1, value:"100", name:"dog", D1: 10, D2: 67, D3: 33},
{id:2, value:"200", name:"cat", D1: 66, D2: 41, D3: 34},
{id:3, value:"300", name:"fish", D1: 23, D2: 45, D3:},
{id:4, value:"400", name:"mouse", D1: 13, D2: 55, D3:},
{id:5, value:"500", name:"snake", D1: 7, D2: 9, D3:}]
In a different function, I return an array of which of these 'keys' I need. This array changes dynamically, so its not possible to type them all out. For example any of the following examples are viable,
useThese1 = ['D1','D2'] //Want exampleDat returned with only these key,value 'columns' returned
useThese2 = ['id','D1','D2','D3'] //Want exampleDat return with only these key,value 'columns' returned
useThese3 = ['value','D2','D3'] //Want exampleDat returned with only these key,value 'columns' returned
So I need to dynamically map the values in a useThese array to the exampleDat array
If I knew the exact columns, I could hand type it ala:
exampleDat.map(d => {return {D1: d.D1, D2: d.D2}})
But I need something like:
dat.map(d => useThese1.map(g => {return {something?}}) ???
In R, it would simply and easily be exampleDat[,colnames(exampleDat) %in% useThese1]
You could map the new keys.
const
mapWith = (array, keys) => array.map(o => Object.fromEntries(keys.map(k => [k, o[k]]))),
data = [{ id: 1, value: "100", name: "dog", D1: 10, D2: 67, D3: 33 }, { id: 2, value: "200", name: "cat", D1: 66, D2: 41, D3: 34 }, { id: 3, value: "300", name: "fish", D1: 23, D2: 45, D3:97}, { id: 4, value: "400", name: "mouse", D1: 13, D2: 55, D3:98}, { id: 5, value: "500", name: "snake", D1: 7, D2: 9, D3:99}],
result1 = mapWith(data, ['D1', 'D2']),
result2 = mapWith(data, ['id', 'D1', 'D2', 'D3']),
result3 = mapWith(data, ['value', 'D2', 'D3']);
console.log(result1);
console.log(result2);
console.log(result3);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Object.fromEntries are relatively recent, but easily polyfilled.
Here is my solution. This uses the ES5 Javascript functions
const selectKeys = (keys, data) => {
return data.map(item => keys.reduce((prev, key) => {
prev[key] = item[key]
return prev
}, {}))
}
const selData1 = selectKeys(useThese1, data)
const selData2 = selectKeys(useThese2, data)
const selData3 = selectKeys(useThese3, data)
You can do something like this
const arr = [
{ id: 1, value: "100", name: "dog", D1: 10, D2: 67, D3: 33 },
{ id: 2, value: "200", name: "cat", D1: 66, D2: 41, D3: 34 },
{ id: 3, value: "300", name: "fish", D1: 23, D2: 45, D3: 34 },
{ id: 4, value: "400", name: "mouse", D1: 13, D2: 55, D3: 34 },
{ id: 5, value: "500", name: "snake", D1: 7, D2: 9, D3: 34 }
];
function dynamicFilter(data, requiredKeys) {
return data.map((item) => {
const result = {};
requiredKeys.forEach(key => result[key] = item[key]);
return result;
});
}
console.log(dynamicFilter(arr, ['D1','D2']));
console.log(dynamicFilter(arr, ['id','D1','D2','D3']));
You can do something like this:
const arr = [{id:1, value:"100", name:"dog", D1: 10, D2: 67, D3: 33}, {id:2, value:"200", name:"cat", D1: 66, D2: 41, D3: 34}, {id:3, value:"300", name:"fish", D1: 23, D2: 45, D3:11}, {id:4, value:"400", name:"mouse", D1: 13, D2: 55, D3:11}, {id:5, value:"500", name:"snake", D1: 7, D2: 9, D3:11}];
const useThese1 = ['D1','D2'];
const useThese2 = ['id','D1','D2','D3'];
const useThese3 = ['value','D2','D3'];
const getResult = (keys) => arr.map(v => keys.reduce((a, c) => (a[c] = v[c], a), {}));
[useThese1, useThese2, useThese3].forEach(v => console.log(getResult(v)));
Here's an imperative way to do it. It could be shortened with ES6 array methods.
let exampleDat = [
{id:1, value:"100", name:"dog", D1: 10, D2: 67, D3: 33},
{id:2, value:"200", name:"cat", D1: 66, D2: 41, D3: 34},
{id:3, value:"300", name:"fish", D1: 23, D2: 45, D3: 8},
{id:4, value:"400", name:"mouse", D1: 13, D2: 55, D3: 8},
{id:5, value:"500", name:"snake", D1: 7, D2: 9, D3: 8}
],
useThese1 = ['D1','D2']
function getColumns(data, useWhich){
let result = [];
for(let row of data){
let keys = Object.keys(row);
let filteredRow = {};
for(let key of keys){
if(useWhich.includes(key)){
filteredRow[key] = row[key];
}
}
result.push(filteredRow);
}
return result;
}
console.log(getColumns(exampleDat, useThese1));
Here's a "for dummies" version of the accepted answer.
(The more verbose variable names helped me understand how the algorithm works.)
const
selectColumns = (unfilteredData, colsToKeep) =>
unfilteredData.map(row =>
Object.fromEntries(colsToKeep.map( col => [col, row[col]] )
)
),
data = [
{ id: 1, value: "100", name: "dog", D1: 10, D2: 67, D3: 33 },
{ id: 2, value: "200", name: "cat", D1: 66, D2: 41, D3: 34 },
{ id: 3, value: "300", name: "fish", D1: 23, D2: 45, D3:97 },
{ id: 4, value: "400", name: "mouse", D1: 13, D2: 55, D3:98 },
{ id: 5, value: "500", name: "snake", D1: 7, D2: 9, D3:99 }
],
colNames1 = ['D1', 'D2'],
result1 = selectColumns(data, colNames1);
console.log(result1);

React - Define greater string between objects

I am calculating the average score of each object ( team ) in my array.
This is my data structure:
const scores = [
{ day: "1", Barcelona: 1, Real: 3, Valencia: 0 },
{ day: "2", Barcelona: 4, Real: 6, Valencia: 3 },
{ day: "3", Barcelona: 7, Real: 7, Valencia: 3 },
{ day: "4", Barcelona: 7, Real: 8, Valencia: 6 }
];
This is how i calculate the average
const getAverage = team => {
if (isNaN(scores[0][team])) return null;
return scores.map(x => x[team]).reduce((a, c) => a + c) / scores.length;
};
I need to establish the object team with the greater number which is the stronger team. How can i do that ?
The stronger team is the team with the higher average.
Here i have done a prototype to reproduce the scenario: https://codesandbox.io/s/recharts-examples-y0y7q
Get the maxAverage from array of teams like so:
this.state = {
homeCity: "Barcelona",
awayCity: "Valencia"
}
const scores = [
{ day: "1", Barcelona: 1, Real: 3, Valencia: 0 },
{ day: "2", Barcelona: 4, Real: 6, Valencia: 3 },
{ day: "3", Barcelona: 7, Real: 7, Valencia: 3 },
{ day: "4", Barcelona: 7, Real: 8, Valencia: 6 }
];
const getAverage = team => {
if (isNaN(scores[0][team])) return null;
return scores.map(x => x[team]).reduce((a, c) => a + c) / scores.length;
};
const maxAverage = teams => {
return teams.map(team => {
return {
team:team,
avg: getAverage(team)
}
}).reduce((a,b)=>a.avg>b.avg?a:b).team
}
console.log(maxAverage([this.state.homeCity,this.state.awayCity]));
You can extend your code, loop through the first element to get all the keys, filter out day key so we left with all the team name, map through team names and get average and then sort
const scores = [
{ day: "1", Barcelona: 1, Real: 3, Valencia: 0 },
{ day: "2", Barcelona: 4, Real: 6, Valencia: 3 },
{ day: "3", Barcelona: 7, Real: 7, Valencia: 3 },
{ day: "4", Barcelona: 7, Real: 8, Valencia: 6 }
];
const getAverage = team => {
if (isNaN(scores[0][team])) return null;
return scores.map(x => x[team]).reduce((a, c) => a + c) / scores.length
};
let stronger = Object.entries(scores[0])
.filter(([key, value]) => key !== 'day')
.map(([key, value]) => [key, getAverage(key)])
.sort((a, b) => b[1] - a[1])
console.log(stronger)

Categories

Resources