I am Beginner in Ionic 2. I want to add to array element as per their position.
for Ex: i have 2 array .
lables:[Lillium,Gerbera,Gerbera,Lillium,Rose,Rose]
Data : [10, 20, 10, 30, 20,10]
Now I want to remove redundancy from labels[] and want to add their values from data[]
My final array should be
labels: [Lillium,Gerbera,Rose]
data : [40,30,30]
I have Extracted Data from Json this type:
var qp = []
for (var i of res.data) {
qp.push(i.quantity_produced);
console.log(res.data);
console.log(qp);
var name = []
for (var i of res.data) {
name.push(i.product);
var s= [new Set(name)];
console.log(res.data);
console.log(name);
Try this:
let labels = ['Lillium', 'Gerbera', 'Gerbera', 'Lillium', 'Rose', 'Rose'];
let Data = [10, 20, 10, 30, 20, 10];
//for each unique label....
let result = [...new Set(labels)]
//... get each occurence index ...
.map(value => labels.reduce((curr, next, index) => {
if (next == value)
curr.push(index);
return curr;
}, []))
//... and reducing each array of indexes using the Data array gives you the sums
.map(labelIndexes => labelIndexes.reduce((curr, next) => {
return curr + Data[next];
}, 0));
console.log(result);
Based on your comment seems that things can be done a lot easier
let data = [{product: 'Lillium',quantity_produced: 10}, {product: 'Gerbera',quantity_produced: 20},{product: 'Gerbera',quantity_produced: 10}, {product: 'Lillium',quantity_produced: 30}, {product: 'Rose',quantity_produced: 20}, {product: 'Rose',quantity_produced: 10}];
let result = data.reduce((curr, next) => {
curr[next.product] = (curr[next.product] || 0) + next.quantity_produced;
return curr;
}, {});
console.log(result);
Related
I'm doing an React assignment for school but I'm a bit stuck and I can't find the right answer.
I have a data file with the following data:
const students = [
{
"name": "Evelyn",
"assignment": "SCRUM",
"difficultyRating": 3,
"funRating": 4
},
{
"name": "Evelyn",
"assignment": "W1D1-1",
"difficultyRating": 3,
"funRating": 3
},
{
"name": "Evelyn",
"assignment": "W1D2-1",
"difficultyRating": 1,
"funRating": 3
}
]
This goes on, there are 10 student and different assignments. What I need to do is get the average of the difficultyRating and funRating per assignment and use this data in a Victory Graph to display. Victory is working but it's not displaying the average.
I have this function already which takes all the assignments and fills it with the other data but I don't know what to do in the next step, how can I make a new Array of objects that I can use in the Victory Chart which displays the average difficulty/funrating per assignment.
The code I have so far is this:
const groupByAssignment = (objectArray, property) => {
return objectArray.reduce(function (total, obj) {
let key = obj[property];
if (!total[key]) {
total[key] = [];
}
total[key].push(obj);
return total;
}, {});
}
let groupedAssignments = groupByAssignment(students, 'assignment');
In the Victory Graph the output looks like this now:
<VictoryBar
style={{
data: {
fill: "#ff0b03",
},
}}
barWidth={2}
data={props.data}
x="assignment"
y="difficultyRating"
/>
)}
What I need is a data piece that has every assignment with the difficulty/rating averaged from all 10 students.
The following will give the average values of fun rating and difficulty rating. I have added more entries as there was only one record for each assignment.
const students = [ { name: "Evelyn", assignment: "SCRUM", difficultyRating: 3, funRating: 4, }, { name: "Pqr", assignment: "SCRUM", difficultyRating: 4, funRating: 2, }, { name: "Evelyn", assignment: "W1D1-1", difficultyRating: 3, funRating: 3, }, { name: "Evelyn", assignment: "W1D2-1", difficultyRating: 1, funRating: 3, }, { name: "Abc", assignment: "W1D2-1", difficultyRating: 5, funRating: 4, }, ];
const groupByAssignmentWithAverage = (objectArray, property) => {
return objectArray.reduce(
(prevValue, { difficultyRating, funRating, [property]: key }) => {
// key is the value of in obj with property as data name
if (!prevValue[key]) {
// create a new entry for each assignment type
prevValue[key] = {
difficultyRatingAvg: difficultyRating,
funRatingAvg: funRating,
count: 1,
};
} else {
// get the previous count and average values
const {count, difficultyRatingAvg, funRatingAvg} = prevValue[key];
prevValue[key] = {
difficultyRatingAvg:
(difficultyRatingAvg + difficultyRating) /
(count + 1),
funRatingAvg: (funRatingAvg + funRating) / (count + 1),
count: count + 1,
};
}
return prevValue;
},
{}
);
};
let output = groupByAssignmentWithAverage(students, "assignment");
console.log(output);
My solution would be to seprate the objects with same assignment name, and then just find the average of that particular assignment by mapping over individual arrays of objects which we get from initial step.
result = students.reduce(function (r, a) {
r[a.assignment] = r[a.assignment] || [];
r[a.assignment].push(a);
return r;
}, Object.create(null));
console.log(result);
Now you can easily format data according to the graph package you are using.
I have an object of the following structure
const obj = {
[name-1]: 'Peter',
[name-2]: 'Mark',
[name-3]: 'Rich',
[age-1]: 25,
[age-2]: 30,
[age-3]: 45
}
I need to split it into 3 separate object like that
const obj1 = {
[name-1]: 'Peter',
[age-1]: 25,
}
const obj2 = {
[name-2]: 'Mark',
[age-2]: 30,
}
const obj3 = {
[name-3]: 'Rich',
[age-3]: 45,
}
How can I achieve that?
Begin by getting entries of the input object using Object.entries
Reduce over the entries generated in step 1
For each iteration's current value split by delimiter '-'
Reduce it to an object, the object will act as a lookup store
Post doing that just extract the values of the lookup.
Transform the individual entries back to its individual object using Object.fromEntries
const obj = {
'name-1': 'Peter',
'name-2': 'Mark',
'name-3': 'Rich',
'age-1': 25,
'age-2': 30,
'age-3': 45
};
const groupedResult = Object.values(Object.entries(obj).reduce((r, c) => {
const [key, val] = c;
const split = key.split('-');
if (!r[split[1]]) {
r[split[1]] = [c];
} else {
r[split[1]].push(c);
}
return r;
}, Object.create(null)))
.map((value) => Object.fromEntries(value));
console.log(groupedResult);
So I have a dilemma.
I have the next code
const loc = [
{ location_key: [32, 22, 11], autoassign: 1 },
{ location_key: [41, 42], autoassign: 1 }
];
const bulkConfigs = [
{
dataValues: {
config_key: 100,
}
},
{
dataValues: {
config_key: 200,
}
}
];
I need to create an object looking like this:
config_key: here get the config key from from bulkConfigs,
location_key: here get the location_key,
autoassign: 1
Also I need this object created
config_key: config_key,
location_key: '',
autoassign: 1,
as many times as they are locations for each config_key, what I mean is in this example from config_key: 200 we will have 2 objects like this one and for config_key: 100 we will have 3 objects like this. I suppose this can be done with reduce ... also bulkConfigs and loc can have more then just 2 objects, but the number will be always the same, like if they are 3 bulkConfigs there will be also 3 loc, but location_key might be different, one can have 7 location_key, other 4, and the last one just 1.
So in other words, the arrys are always the same length and they are always in the same order so they have the same index. Only the location_key can change, and I need the object created as many times as location_key exist.
I have tried a few things, but I don't know when it comes to this stuff .... I just can't do, that's what happens when you start with react and not java script :)
Ok so I managed to do this using lodash, here is my solution, I know it's nested like hell and probably this could be done way easier, but for a newbie is good enough. Feel free to come with more elegant solutions.
If you have a similar problem, here is the solution.
A code sandbox so you can play with:
https://codesandbox.io/s/epic-field-bdwyi?file=/src/index.js
import _ from "lodash";
const locs = [{ location_key: [32, 22, 11] }, { location_key: [41, 42] }];
const bulkConfigs = [
{
dataValues: {
config_key: 100
}
},
{
dataValues: {
config_key: 200
}
}
];
// map over the array of bulckConfigs and get indexes
const mergedArrays = _.map(bulkConfigs, (bulkConfig, i) => {
// create the object that we need
const objectNeed = {
// flatMap over the locs array to get flat values from objects in it
location_key: _.flatMap(locs, ({ location_key }, index) => {
// match the indexs of both arrays
if (index === i) {
// return the location_key values for each config
return location_key;
} else {
// compact to remove the undefinded values returned
return _.compact();
}
}),
config_key: bulkConfig.dataValues.config_key,
autoassign: 1
};
return objectNeed;
});
// now we just need to crate the same object as many locations and use flatMap to flatten the objects
const allObjects = _.flatMap(mergedArrays, mergedArray => {
const yy = _.map(mergedArray.location_key, location => {
const zz = {
location_key: location,
config_key: mergedArray.config_key,
autoassign: 1
};
return zz;
});
return yy;
});
console.log(allObjects);
And the more elegant version of it :)
const getConfigs = (locEl, index) => {
return _.map(locEl.location_key, (locationKey) => {
return {
location_key: locationKey,
config_key: bulkConfigs[index].dataValues.config_key,
autoassign: 1,
};
});
};
const configLocations = _.chain(locs)
.map(getConfigs)
.flatten()
.value();
console.log(configLocations);
I am using react-table.js to take data from a form, but I want to be able to delete the data out of the table. The button is working so I know that is attached properly, but I can't seem to get it to delete.
Here is the code
handleDelete = item => {
var newArr = [];
const newState = this.props.documentation;
for (var key in newState) {
if (newState.hasOwnProperty(key)) {
let data = newState[key];
data.id = key;
newArr.push(newState[key]);
}
const sliceArr = newArr.slice();
if (sliceArr.indexOf(item) > -1) {
sliceArr.slice(sliceArr.indexOf(item), 1);
}
console.log('New Array', sliceArr);
this.setState({ data: sliceArr });
}
};
Along with the button I am attaching it to
Cell: row => (
<div>
<button onClick={() => this.handleDelete(row.id)}>Delete</button>
</div>
You're looking for splice rather than slice:
const spliceArr = newArr.slice();
if (spliceArr.indexOf(item) > -1) {
spliceArr.splice(spliceArr.indexOf(item), 1);
}
console.log('New Array', spliceArr);
this.setState({ data: spliceArr });
Example:
const newArr = [1, 2, 3, 4]
// [1, 2, 3, 4] example
const spliceArr = newArr.slice()
// [1, 2, 3, 4] ok
spliceArr.slice(spliceArr.indexOf(3), 1)
spliceArr
// [1, 2, 3, 4] oops
spliceArr.splice(spliceArr.indexOf(3), 1)
spliceArr
// [1, 2, 4] better
If that doesn't get you all the way there, you may want to update your question with the rendering (presumably JSX) of the table itself, as #MichaelBenin suggested.
Suppose I have an array arr with several elements. I want to create an array of groups of elements of arr (array of arrays), in which each group is composed of the next element that matched some condition fn and every next element in sequence until the next match.
So I want to kinda slice the array in groups starting by matching elements.
I made the following code to do it, but it's too imperative to me:
var sliceGroupingBy = (arr, fn) => {
var newArray = [];
arr.forEach(el => {
if (fn(el)) {
newArray.push([el]);
} else {
newArray.slice(-1)[0].push(el);
}
});
return newArray;
};
Example:
var in = [1, 2, 4, 6, 3, 4, 6, 5, 7, 8, 8, 1];
var out = sortaGroupBy(in, x => x % 2 === 1);
// [ [ 1, 2, 4, 6 ], [ 3, 4, 6 ], [ 5 ], [ 7, 8, 8 ], [ 1 ] ]
I wonder what's the more functional way to do it, using the regular functional operations only (no if or aux. array).
You can always make it more functional by using reduce instead of some imperative looping:
function sliceGroupingBy(arr, fn) {
return arr.reduce((newArray, el) => {
if (fn(el))
newArray.push([el]);
else
newArray[newArray.length-1].push(el);
return newArray;
}, []);
}
If you also want to avoid the push and, for whatever reasons, statements at all, you can concat:
const sliceGroupingBy = (arr, fn) =>
arr.reduce((newArray, el) =>
fn(el)
? newArray.concat([[el]]);
: newArray.slice(0, -1).concat(newArray.slice(-1).map(lastArray =>
lastArray.concat([el])
)
, []);
("altering" the last element of the array could be done in a myriad of ways)
Grossly inefficient but:
let predicate = x => x % 2 === 1;
let partition = (pred, arr) => {
let res1 = arr.filter(pred);
let res2 = arr.filter(x => !pred(x));
return [res1, res2];
};
partition(predicate, [1,2,3,...]);
I'd never do it that way in JavaScript though (assume from the code that's the language in question). See my comments on your question.
EDIT
Per the comment that I was wrong about what you're doing,
let xs = array.reduce((acc, x, i, arr) => {
let lastIndex = acc.reduce((y, z) => { y + z.length }, 0);
return predicate(x) || i === arr.length - 1 ?
acc.concat([arr.slice(lastIndex, i)]) :
acc;
}, []);
Uses no statements, only expressions, no mutation, only copying. I still wouldn't do this without using immutable.js or mori. Its rather expensive.
EDIT 2
More efficient version of the last approach based on comment from Bergi:
let {result} = array.reduce((obj, x, i, arr) => {
let {lastIndex, result} = obj;
let passes = predicate(x) || i === arr.length - 1;
return {
lastIndex: passes ? i : lastIndex,
result: passes ? result.concat([arr.slice(lastIndex, i)]) : result
};
}, { lastIndex: 0, result: [] });