如何在过滤和映射后获取用户ID

时间:2019-06-22 01:13:01

标签: javascript arrays object

嗨,我试图为每个服务创建一个名称和用户ID的对象,我希望该对象看起来像这样:

const object = {
    name: Netflix, user: (user id who pays max price for this provider)
    name: Comcast, user: (same)
    name: Verizon, user: (same)
}

我尝试更改map返回中的object属性,但是它不起作用,而且我已经完成了对象的一半工作,意思是使用提供者的名称,现在我需要另一个键值对

const services = [
     { userid: 1, providerId: 1, ammount: 250000 },
     { userid: 4, providerId: 3, ammount: 280900 },
     { userid: 6, providerId: 3, ammount: 31000 },
     { userid: 2, providerId: 2, ammount: 58600 },
     { userid: 3, providerId: 1, ammount: 13000 },
     { userid: 5, providerId: 2, ammount: 5000 },
     { userid: 3, providerId: 3, ammount: 59900 },
     { userid: 6, providerId: 3, ammount: 9500 }
]

const providers = [
    { id: 1, name: Netflix },
    { id: 2, name: Comcast },
    { id: 3, name: Verizon }
]

这是我的职责

function getUserId(providerId) {
    return services.filter(function(obj) {
        if (obj.providerId == providerId)
            return obj.providerId;
    }).map(function(obj) { return obj.ammount });
}

function getMaxUserId(providerId) {
    return Math.max(...getUserId(providerId));
}

providers.forEach(prov => {
    object[prov.name] = getUserId(prov.id);
})

如您所见,我首先过滤整个数组以查找具有特定providerId的提供者,然后创建一个新的带有map函数的数组,该函数填充了该特定提供者的所有“数量”,最后我搜索了该数组的最大数量数组,那么一切正常,它会为每个提供商返回正确的最大金额,但我也想获取为每个提供商支付最多的用户ID

实际上我正在得到这样的对象:

[
   {name: Netflix, user: 250000},
   {name: Comcast, user: 58600},
   {name: Verizon, user: 280900}
]

我需要这个:

[
   {name: Netflix, user: 1},
   {name: Comcast, user: 2},
   {name: Verizon, user: 4}
]

4 个答案:

答案 0 :(得分:3)

您也可以在sortamount进行服务。然后,您可以通过providerId对它们进行分组,最后在提供程序上进行映射以获得所需的输出:

const services = [ { id: 1, providerId: 1, ammount: 250000 }, { id: 4, providerId: 3, ammount: 280900 }, { id: 6, providerId: 3, ammount: 31000 }, { id: 2, providerId: 2, ammount: 58600 }, { id: 3, providerId: 1, ammount: 13000 }, { id: 5, providerId: 2, ammount: 5000 }, { id: 3, providerId: 3, ammount: 59900 }, { id: 6, providerId: 3, ammount: 9500 } ]
const providers = [ { id: 1, name: 'Netflix' }, { id: 2, name: 'Comcast' }, { id: 3, name: 'Verizon' } ] 

let grouped = services
  .sort((a,b) => b.ammount - a.ammount)  // sort `desc`
  .reduce((r,c) => ((r[c.providerId] = r[c.providerId] || []).push(c), r), {})
	
let result = providers.map(p => ({name: p.name, user: grouped[p.id][0].id}))

console.log(result)

您还可以跳过上面的sort并检查ammount并基于pushunshift

const services = [ { id: 1, providerId: 1, ammount: 250000 }, { id: 4, providerId: 3, ammount: 280900 }, { id: 6, providerId: 3, ammount: 31000 }, { id: 2, providerId: 2, ammount: 58600 }, { id: 3, providerId: 1, ammount: 13000 }, { id: 5, providerId: 2, ammount: 5000 }, { id: 3, providerId: 3, ammount: 59900 }, { id: 6, providerId: 3, ammount: 9500 } ]
const providers = [ { id: 1, name: 'Netflix' }, { id: 2, name: 'Comcast' }, { id: 3, name: 'Verizon' } ] 

let groupedById = services.reduce((acc, cur) => { 
  let k = cur.providerId
  acc[k] = acc[k] || []
  if(acc[k][0] && acc[k][0].ammount > cur.ammount) acc[k].push(cur)
  else acc[k].unshift(cur)
  return acc
}, {})

let result = providers.map(({name, id}) => ({name, user: groupedById[id][0].id}))

console.log(result)

这样,您只有一个Array.reduce和一个Array.map,它们将比原始版本的more performantforEach和{{1 }}。

答案 1 :(得分:1)

理想情况下,我们在JS中有argmax。但就目前而言,普通迭代看起来更好。请注意很少见的==,因为JS将字典键转换为字符串:

var maxes = {};
services.forEach(item => {
    if(!maxes[item.providerId] || maxes[item.providerId] < item.ammount[0]) {
        maxes[item.providerId] = [item.ammount, item.id];
    }
});
function providerById(id) {
    return providers.filter(p => p.id == key)[0].name;
}
console.log(Object.keys(maxes).map(key => {
    return { name: providerById(key), user: maxes[key][1] };
}));

答案 2 :(得分:1)

并且,作为解决问题的第三种可能的方法(在我的评论之后),您可以使用类似的内容(可以修改对象,但是您更喜欢自己的想法,但是我建议您摆脱{{ 1}}和name键):

user

使用此解决方案的情况下的输出如下所示:

const object = {};

function getUserId(providerId) {
    return services.filter(function(obj) {
        if (obj.providerId == providerId)
            return obj.providerId;
    }).map(function(obj) { return obj });
}

function getMaxUserId(output) {
    let amm = output.map( (o) => { return o.ammount; } );
    let idx = amm.indexOf(Math.max(...amm));
    return output[idx].userid;
}

providers.forEach(prov => {
    object[prov.name] = getMaxUserId(getUserId(prov.id));
})

console.log(object)

Ofc,只需稍作调整,您就可以返回一个Object { Netflix: 1, Comcast: 2, Verizon: 4 } 带有最初打算的对象(别忘了将Array分配给object):

[]

在后一种情况下,输出将如下所示:

providers.forEach(prov => {
  object.push( {name:prov.name,user:getMaxUserId(getUserId(prov.id))} )
})

答案 3 :(得分:0)

尝试以下代码。

function getUser(providerId) {
    let arr = services.filter(v => { // filters for this provider
        return v.providerId == providerId;
    });

    return arr.sort((a, b) => { // sorts from highest to lowest amount
        if (a.ammount > b.ammount) {
            return -1;
        }
        if (a.ammount < b.ammount) {
            return 1;
        }
        return 0;
    })[0]; // returns the first obj in the sorted array
}

var result = [];
providers.forEach(prov => {
    result.push({
        name: prov.name,
        userDetails: getUser(prov.id)
    });
});
console.log(result);

JSFiddle