嗨,我试图为每个服务创建一个名称和用户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}
]
答案 0 :(得分:3)
您也可以在sort
上amount
进行服务。然后,您可以通过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
并基于push
或unshift
:
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 performant
,forEach
和{{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);