var myArray = [
{"Emiten_ID":'SMBR',"Lot":500,"Price":2500},
{"Emiten_ID":'SMBR',"Lot":300,"Price":2200},
{"Emiten_ID":'ELSA',"Lot":500,"Price":1000},
{"Emiten_ID":'SMBR',"Lot":100,"Price":3000},
{"Emiten_ID":'BI',"Lot":300,"Price":500},
{"Emiten_ID":'AAI',"Lot":200,"Price":1300},
{"Emiten_ID":'BTB',"Lot":700,"Price":2900},
{"Emiten_ID":'BI',"Lot":150,"Price":200},
{"Emiten_ID":'AAI',"Lot":200,"Price":600},
];
i want result like this, where i get sum from lot and max value from price
var Result= [
{"Emiten_ID":'ELSA',"Lot":500,"Price":1000},
{"Emiten_ID":'SMBR',"Lot":900,"Price":3000},
{"Emiten_ID":'BI',"Lot":450,"Price":500},
{"Emiten_ID":'BTB',"Lot":700,"Price":2900},
{"Emiten_ID":'AAI',"Lot":400,"Price":1300},
];
var myArray = [
{"Emiten_ID":'SMBR',"Lot":500,"Price":2500},
{"Emiten_ID":'SMBR',"Lot":300,"Price":2200},
{"Emiten_ID":'ELSA',"Lot":500,"Price":1000},
{"Emiten_ID":'SMBR',"Lot":100,"Price":3000},
{"Emiten_ID":'BI',"Lot":300,"Price":500},
{"Emiten_ID":'AAI',"Lot":200,"Price":1300},
{"Emiten_ID":'BTB',"Lot":700,"Price":2900},
{"Emiten_ID":'BI',"Lot":150,"Price":200},
{"Emiten_ID":'AAI',"Lot":200,"Price":600},
];
i want result like this, where i get sum from lot and max value from price
var Result= [
{"Emiten_ID":'ELSA',"Lot":500,"Price":1000},
{"Emiten_ID":'SMBR',"Lot":900,"Price":3000},
{"Emiten_ID":'BI',"Lot":450,"Price":500},
{"Emiten_ID":'BTB',"Lot":700,"Price":2900},
{"Emiten_ID":'AAI',"Lot":400,"Price":1300},
];
Share
Improve this question
asked Sep 20, 2016 at 5:24
muhammad furqonmuhammad furqon
771 silver badge2 bronze badges
1
- 2 I don't see any JavaScript (other than the problem and a desired result), what have you tried with JavaScript? Please provide a minimal reproducible example. – zer00ne Commented Sep 20, 2016 at 5:46
8 Answers
Reset to default 3You could use Array#forEach
and an object as hash table and group it by Emiten_ID
.
var myArray = [{ "Emiten_ID": 'SMBR', "Lot": 500, "Price": 2500 }, { "Emiten_ID": 'SMBR', "Lot": 300, "Price": 2200 }, { "Emiten_ID": 'ELSA', "Lot": 500, "Price": 1000 }, { "Emiten_ID": 'SMBR', "Lot": 100, "Price": 3000 }, { "Emiten_ID": 'BI', "Lot": 300, "Price": 500 }, { "Emiten_ID": 'AAI', "Lot": 200, "Price": 1300 }, { "Emiten_ID": 'BTB', "Lot": 700, "Price": 2900 }, { "Emiten_ID": 'BI', "Lot": 150, "Price": 200 }, { "Emiten_ID": 'AAI', "Lot": 200, "Price": 600 }, ],
result = [];
myArray.forEach(function (a) {
if (!this[a.Emiten_ID]) {
this[a.Emiten_ID] = { Emiten_ID: a.Emiten_ID, Lot: 0, Price: 0 };
result.push(this[a.Emiten_ID]);
}
this[a.Emiten_ID].Lot += a.Lot;
this[a.Emiten_ID].Price = Math.max(this[a.Emiten_ID].Price, a.Price);
}, Object.create(null));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES6 with a closure of hash
without use of this
.
var myArray = [{ "Emiten_ID": 'SMBR', "Lot": 500, "Price": 2500 }, { "Emiten_ID": 'SMBR', "Lot": 300, "Price": 2200 }, { "Emiten_ID": 'ELSA', "Lot": 500, "Price": 1000 }, { "Emiten_ID": 'SMBR', "Lot": 100, "Price": 3000 }, { "Emiten_ID": 'BI', "Lot": 300, "Price": 500 }, { "Emiten_ID": 'AAI', "Lot": 200, "Price": 1300 }, { "Emiten_ID": 'BTB', "Lot": 700, "Price": 2900 }, { "Emiten_ID": 'BI', "Lot": 150, "Price": 200 }, { "Emiten_ID": 'AAI', "Lot": 200, "Price": 600 }, ],
result = [];
myArray.forEach((hash => a => {
if (!hash[a.Emiten_ID]) {
hash[a.Emiten_ID] = { Emiten_ID: a.Emiten_ID, Lot: 0, Price: 0 };
result.push(hash[a.Emiten_ID]);
}
hash[a.Emiten_ID].Lot += a.Lot;
hash[a.Emiten_ID].Price = Math.max(hash[a.Emiten_ID].Price, a.Price);
})(Object.create(null)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Using Map class available in ECMAScript 2015 (or polyfill):
var myArray = [{ "Emiten_ID": 'SMBR', "Lot": 500, "Price": 2500 }, { "Emiten_ID": 'SMBR', "Lot": 300, "Price": 2200 }, { "Emiten_ID": 'ELSA', "Lot": 500, "Price": 1000 }, { "Emiten_ID": 'SMBR', "Lot": 100, "Price": 3000 }, { "Emiten_ID": 'BI', "Lot": 300, "Price": 500 }, { "Emiten_ID": 'AAI', "Lot": 200, "Price": 1300 }, { "Emiten_ID": 'BTB', "Lot": 700, "Price": 2900 }, { "Emiten_ID": 'BI', "Lot": 150, "Price": 200 }, { "Emiten_ID": 'AAI', "Lot": 200, "Price": 600 }, ]
var temp = new Map();
for (var item of myArray) {
var e = temp.get(item.Emiten_ID)
if (e) {
e.Lot += item.Lot;
e.Price = Math.max( e.Price, item.Price );
} else {
temp.set( item.Emiten_ID,
{ Emiten_ID: item.Emiten_ID, Lot:item.Lot, Price:item.Price })
}
}
var result = Array.from(temp.values());
console.log(result)
You can use linq.js library:
var myArray = [
{"Emiten_ID":'SMBR',"Lot":500,"Price":2500},
{"Emiten_ID":'SMBR',"Lot":300,"Price":2200},
{"Emiten_ID":'ELSA',"Lot":500,"Price":1000},
{"Emiten_ID":'SMBR',"Lot":100,"Price":3000},
{"Emiten_ID":'BI',"Lot":300,"Price":500},
{"Emiten_ID":'AAI',"Lot":200,"Price":1300},
{"Emiten_ID":'BTB',"Lot":700,"Price":2900},
{"Emiten_ID":'BI',"Lot":150,"Price":200},
{"Emiten_ID":'AAI',"Lot":200,"Price":600},
];
var answer = Enumerable.From(myArray).GroupBy("x => x.Emiten_ID", "x => {Lot: x.Lot, Price: x.Price}").Select("x => {Emiten_ID:x.Key(), Lot:x.Sum(y=>y.Lot), Price:x.Max(y=>y.Price)}").ToArray();
answer.forEach(x => console.log(x));
<script data-require="[email protected]" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
<script data-require="[email protected]+2" data-semver="2.2.0+2" src="//cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.js"></script>
<script data-require="[email protected]+2" data-semver="2.2.0+2" src="//cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/jquery.linq.js"></script>
this is long way to this, hope there is simpler way do this.
var myArray = [
{"Emiten_ID":'SMBR',"Lot":500,"Price":2500},
{"Emiten_ID":'SMBR',"Lot":300,"Price":2200},
{"Emiten_ID":'ELSA',"Lot":500,"Price":1000},
{"Emiten_ID":'SMBR',"Lot":100,"Price":3000},
{"Emiten_ID":'BI',"Lot":300,"Price":500},
{"Emiten_ID":'AAI',"Lot":200,"Price":1300},
{"Emiten_ID":'BTB',"Lot":700,"Price":2900},
{"Emiten_ID":'BI',"Lot":150,"Price":200},
{"Emiten_ID":'AAI',"Lot":200,"Price":600},
];
var sortedIds = [];
var Result = [];
function sortArray(){
for(var i = 0; i < myArray.length; i++){
if(myArray.indexOf(myArray[i].Emiten_ID) < 0){
sortedIds.push(myArray[i].Emiten_ID);
Result.push({
"Emiten_ID" : myArray[i].Emiten_ID,
"Lot" : sumLot(myArray[i].Emiten_ID),
"Price" : maxPrice(myArray[i].Emiten_ID);
});
}
}
//out put
console.log(Result);
}
function sumLot(id){
var sum = 0;
for(var i = 0; i < myArray.length; i++){
if(myArray[i].Emiten_ID == id){
sum += myArray[i].lot;
}
}
return sum;
}
function maxPrice(id){
var max = 0;
for(var i = 0; i < myArray.length; i++){
if(myArray[i].Price > max){
max = myArray[i].Price;
}
}
return max;
}
var myArray = [
{"Emiten_ID":'SMBR',"Lot":500,"Price":2500},
{"Emiten_ID":'SMBR',"Lot":300,"Price":2200},
{"Emiten_ID":'ELSA',"Lot":500,"Price":1000},
{"Emiten_ID":'SMBR',"Lot":100,"Price":3000},
{"Emiten_ID":'BI',"Lot":300,"Price":500},
{"Emiten_ID":'AAI',"Lot":200,"Price":1300},
{"Emiten_ID":'BTB',"Lot":700,"Price":2900},
{"Emiten_ID":'BI',"Lot":150,"Price":200},
{"Emiten_ID":'AAI',"Lot":200,"Price":600},
];
myArray = myArray.sort(function(a,b){
if(a.Emiten_ID > b.Emiten_ID)
return 1;
else if(a.Emiten_ID < b.Emiten_ID)
return -1;
else{
return a.Price - b.Price;
}
});
var result = [myArray[0]];
for(var i = 1 ; i < myArray.length ; i ++){
var obj = myArray[i];
var res = result[result.length - 1];
if(obj.Emiten_ID == res.Emiten_ID){
res.Lot += obj.Lot;
res.Price = Math.max(res.Price,obj.Price);
}else{
result.push(obj);
}
}
console.log(result);
Solution using lodash:
_.chain(myArray).groupBy('Emiten_ID').map(emiten => ({
"Emiten_ID":emiten[0]['Emiten_ID'],
"Lot": _.sumBy(emiten, 'Lot'),
"Price": _.maxBy(emiten, 'Price')['Price']
})).value()
- Iterate all the
array
elements - Find the index of
each-element
from new array - If element does not exist, push it in
array
- If element exists, sum the value of
Lot
and if value ofPrice
is heigher, over-ride the heigher value
var myArray = [{
"Emiten_ID": 'SMBR',
"Lot": 500,
"Price": 2500
}, {
"Emiten_ID": 'SMBR',
"Lot": 300,
"Price": 2200
}, {
"Emiten_ID": 'ELSA',
"Lot": 500,
"Price": 1000
}, {
"Emiten_ID": 'SMBR',
"Lot": 100,
"Price": 3000
}, {
"Emiten_ID": 'BI',
"Lot": 300,
"Price": 500
}, {
"Emiten_ID": 'AAI',
"Lot": 200,
"Price": 1300
}, {
"Emiten_ID": 'BTB',
"Lot": 700,
"Price": 2900
}, {
"Emiten_ID": 'BI',
"Lot": 150,
"Price": 200
}, {
"Emiten_ID": 'AAI',
"Lot": 200,
"Price": 600
}];
var newArr = [];
myArray.forEach(function (el) {
var findIndex = newArr.findIndex(function (item) {
return item.Emiten_ID === el.Emiten_ID;
});
if (findIndex === -1) {
newArr.push(el);
} else if (el.Price > newArr[findIndex].Price) {
newArr[findIndex].Price = el.Price;
newArr[findIndex].Lot += el.Lot;
} else {
newArr[findIndex].Lot += el.Lot;
}
});
console.log(JSON.stringify(newArr, null, 4));
Let's try to decompose this. We'll start by writing a generic utility function which we will call combine
, which combines properties on objects using a function specified for each property in a hash called combiners
:
function combine(array, combiners) {
const result = {};
for (prop of Object.keys(combiners)) {
result[prop] = combiners[prop](...array.map(elt => elt[prop]));
}
return result;
}
Example of using this:
combine(
[{a: 1, b: 10}, {a: 42, b: 80}],
{a: sum, b: Math.max}
)
which will result in
{a: 43, b: 80}
Of course, to make this work, we'll have to define sum
:
function sum(...vals) { return vals.reduce(add); }
where add
is just
function add(a, b) { return a + b; }
Next, we will group the input by the Emiten_ID
property. You could use Underscore's _.groupBy
for this, or write your own (see below).
const groups = _.groupBy(myArray, 'Emiten_ID`);
This will result in something looking like
{ SMBR: [
{ Emiten_ID: 'SMBR', "Lot": 500, "Price": 2500},
{ Emiten_ID: 'SMBR', "Lot": 300, "Price": 2200}
],
ELSA: [
]
}
After doing this prep work, it is pretty easy to get the result, by just mapping each value in groups
using our combine
utility:
const Result = Object.keys(groups).map(key =>
combine(
groups[key],
{
Emiten_ID: identity,
Lot: sum,
Price: Math.max}));
where identity
is just
function identity(id) { return id; }
If you'd prefer to abstract away the notion inside combine
of mapping object properties, you could use some utility from Underscore again, or write it yourself:
function mapObject(obj, fn) {
const result = {};
for (prop of obj) result[prop] = fn(obj[prop], prop);
return result;
}
Example of using this:
mapObject({a: 2, b: 3}, x => x * x)
// yields {a: 4, b: 9}
Now you can write combine
a bit more simply, as
function combine(array, combiners) {
return mapObject(combiners, function(combiner, prop) {
return combiner(...array.map(elt => elt[prop]));
};
}
In case you don't want to use Underscore's _.groupBy
, here's a home grown version:
function groupBy(array, prop) {
var result = {};
array.forEach(elt => (result[elt[prop]] = result[elt[prop]] || []).push(elt));
return result;
}