XamDev
XamDev

Reputation: 3647

Concatenate array in vue.js

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 !

Upvotes: 0

Views: 1707

Answers (4)

Caio Santos
Caio Santos

Reputation: 1805

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!

Upvotes: 1

James
James

Reputation: 22227

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"));

Upvotes: 1

Hassan Imam
Hassan Imam

Reputation: 22524

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; }

Upvotes: 1

user15118714
user15118714

Reputation:

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

 });

Upvotes: 2

Related Questions