0

I have following array with me where records are shown per user

let data = [
  { userid: 1, placename: abc,  price: 10 },
  { userid: 1, placename: pqr,  price: 20 },  
  { userid: 1, placename: xyz , price: 30},
  { userid: 2, placename: abc , price: 40},
  { userid: 2, placename: lmn , price: 50}

So, I want to transpose this data group by userid, by concatenation of place name and sum of price. It should be look like below

UseId   PlaceName   Price
1       abc,xyz,pqr 60
2       abc,lmn     90

And I am binding this data to bootstrap vue b-table component As of now I have done like this

 groupby: function(array, key) {
            const result = {};
            array.forEach(item => {
                if (!result[item[key]]) {
                    result[item[key]] = [];
                }
                result[item[key]].push(item);
            });
           
            return result;
        },

And calling this while view is getting initialized,

groupby(this.list,'userid');

though I am getting all records in row as per user, but I am not able to concatenate the values and doing total.

While binding to table it is giving error 'Expected Arrat,got object'

Is anything missing here !

Any help on this appreciated !

4 Answers 4

2

Try out to filter the items that have the same userid then join place names and sum their prices :

 array.forEach(item => {
                if (!result[item[key]]) {
                    result[item[key]] = [];
                }
        let matched=array.filter(el=>el.UseId===item.UseId);
         result[item[key]].push(
           {
              UseId:item.UseId,
              placeName:matched.map(e=>e.placename).join(),
              Price:matched.reduce((a, b) => a + b.price, 0)

           });//push end

 });
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks ...Its working.. But still it give me 5 rows(As shown in the problem statement) though it is concat the place name and doing sum of price. Also, it gives [undefined: Array(5)] .. Though it has the 5 records it.. But not sure why undefined ? I am delcaring the results as let result=[]; Is that a problem ?
1

You can group your array item based on userid and push placename into array and sum up price for same userid.

const data = [ { userid: 1, placename: 'abc', price: 10 }, { userid: 1, placename: 'pqr', price: 20 }, { userid: 1, placename: 'xyz' , price: 30}, { userid: 2, placename: 'abc' , price: 40}, { userid: 2, placename: 'lmn' , price: 50}],
    result = Object.values(data.reduce((r,o) => {
      r[o.userid] = r[o.userid] || {userid: o.userid, placename: [], price: 0};
      r[o.userid].placename.push(o.placename);
      r[o.userid].price += o.price;
      return r;
    },{}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

1

Whenever you feel like making an empty object and using array.map to populate it, try using .reduce instead

const data = [
  { userid: 1, placename: "abc",  price: 10 },
  { userid: 1, placename: "pqr",  price: 20 },  
  { userid: 1, placename: "xyz" , price: 30},
  { userid: 2, placename: "abc" , price: 40},
  { userid: 2, placename: "lmn" , price: 50}
];

const groupBy = (arr, key) => Object.values(
  arr.reduce((acc, item) => {
    const k = item[key];
    if (!acc[k]) {
      acc[k] = {...item};
    } else {
      acc[k].placename += "," + item.placename;
      acc[k].price += item.price;
    }
    return acc;
  }, {})
);

console.log(groupBy(data, "userid"));

2 Comments

It works great... Only difference is instead of placeName array its a string value with concat of placeName...i have made that change.. Only problem i am facing is, it is concatenating the ',' at start. Like this: placeName = ,abc,pqr,xyz
Im not sure, are you trying to make it return a comma separated string of placenames? Because this does just that.
1

I split the solution in 3 steps, X, Y and Z:

X = group the rows by userid;

Y = concat the placenames and sum the prices;

Z = make a simpler object.

let data = [
    { userid: 1, placename: 'abc', price: 10 },
    { userid: 1, placename: 'pqr', price: 20 },
    { userid: 1, placename: 'xyz', price: 30 },
    { userid: 2, placename: 'abc', price: 40 },
];

const X = data.reduce((a, { userid, placename, price }) => { a[userid] = [...(a[userid] || []), { placename, price }]; return a }, {})
const Y = Object.entries(X).map(([userid, items]) => { return [userid, items.reduce((a, c) => { a.placename = [...a.placename.split(',').filter(s => !!s), c.placename].join(','); a.price += c.price; return a; }, { placename: '', price: 0 })]; });
const Z = Y.map(([userid, { placename, price }]) => ({ userid, placename, price }))

console.log(Z)

You can use a single line solution too:

let data = [
    { userid: 1, placename: 'abc', price: 10 },
    { userid: 1, placename: 'pqr', price: 20 },
    { userid: 1, placename: 'xyz', price: 30 },
    { userid: 2, placename: 'abc', price: 40 },
]
const doIt = (data) => Object.entries(data.reduce((a, { userid, placename, price }) => { a[userid] = [...(a[userid] || []), { placename, price }]; return a }, {})).map(([userid, items]) => { return [userid, items.reduce((a, c) => { a.placename = [...a.placename.split(',').filter(s => !!s), c.placename].join(','); a.price += c.price; return a; }, { placename: '', price: 0 })]; }).map(([userid, { placename, price }]) => ({ userid, placename, price }))
console.log(doIt(data))

Have fun!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.