繁体   English   中英

如何根据javascript中的最大值从对象数组中删除对象

[英]How can I remove an object from array of objects based on max value in javascript

我有一个像这样的对象数组:

[ { person: 'Fred', scoreTotal: 29 },
{ person: 'Alice', scoreTotal: 34 },
{ person: 'Alice', scoreTotal: 22 },
{ person: 'Mary', scoreTotal: 14 },
{ person: 'Bob', scoreTotal: 33 },
{ person: 'Bob', scoreTotal: 13 },
{ person: 'Bob', scoreTotal: 22 },
{ person: 'Joe', scoreTotal: 28 }]

并且对于给定的人有多个对象 - >我想保持顶部的“X”。 例如:

一个。 一个人的前1个结果结果如下所示:

    [ { person: 'Fred', scoreTotal: 29 },
    { person: 'Alice', scoreTotal: 34 },
    { person: 'Mary', scoreTotal: 14 },
    { person: 'Bob', scoreTotal: 33 },
    { person: 'Joe', scoreTotal: 28 }]

一个人的前2个结果结果如下所示:

   [ { person: 'Fred', scoreTotal: 29 },
  { person: 'Alice', scoreTotal: 34 },
   { person: 'Alice', scoreTotal: 22 },
   { person: 'Mary', scoreTotal: 14 },
   { person: 'Bob', scoreTotal: 33 },
   { person: 'Bob', scoreTotal: 22 },
   { person: 'Joe', scoreTotal: 28 }]

有没有办法用Lodash这样的东西来实现这个目标?

我想我正朝着正确的方向前进但尚未完全:

for (var i = 0; i < t.length - 1; i++) {
if (
  t[i].golfer === t[i + 1].golfer &&
  t[i].scoreTotal < t[i + 1].scoreTotal
) {
  delete t[i];
}

}

//删除“未定义的条目”

t = t.filter(function(el) {
    return typeof el !== "undefined";
});
console.log(t);

没有Underscore / Lodash,你可以很简单地做到这一点。 按分数将数组从最高到最低排序。 然后使用Array.filter 当过滤器通过阵列时,记录您看到每个人的次数,并在达到您想要的最高号码后开始返回false。

 let arr = [ { person: 'Fred', scoreTotal: 29 },{ person: 'Alice', scoreTotal: 34 },{ person: 'Alice', scoreTotal: 22 },{ person: 'Mary', scoreTotal: 14 },{ person: 'Bob', scoreTotal: 33 },{ person: 'Bob', scoreTotal: 13 },{ person: 'Bob', scoreTotal: 22 },{ person: 'Joe', scoreTotal: 28 }] function filterTop(arr, top) { let counts = {} return [...arr].sort((a, b) => b.scoreTotal - a.scoreTotal) .filter(score => (counts[score.person] = (counts[score.person] || 0) +1 ) <= top) } console.log(filterTop(arr, 1)) console.log(filterTop(arr, 2)) 

仅使用ES6,您可以使用2 reduce s。 首先是对数组进行分组。 第二是获得每组最高人数。

 let arr = [{"person":"Fred","scoreTotal":29},{"person":"Alice","scoreTotal":34},{"person":"Alice","scoreTotal":22},{"person":"Mary","scoreTotal":14},{"person":"Bob","scoreTotal":33},{"person":"Bob","scoreTotal":13},{"person":"Bob","scoreTotal":22},{"person":"Joe","scoreTotal":28}]; let getTop = (a, t) => { //Parameters a = array. t = top return Object.values(a.reduce((c, v) => { //Group the array using the person property c[v.person] = c[v.person] || []; c[v.person].push(v); return c; }, {})).reduce((c, v) => { v.sort((a, b) => b.scoreTotal - a.scoreTotal); //Sort the sub array c = c.concat(v.slice(0, t)); //Add the top to accumulator return c; }, []); } let result1 = getTop(arr, 1); //Get top 1 let result2 = getTop(arr, 2); //Get top 2 console.log('Top 1', result1); console.log('Top 2', result2); 

这是lodash的解决方案......

function pickTopX(data, x) {
  let grouped = _.groupBy(data, 'person');
  let sorted = _.sortBy(grouped, 'scoreTotal');
  let sliced = _.map(sorted, function(pair) {
    return _.take(pair, x)
  });
  let result = _.flatten(sliced);
  return result;
}

使用您尝试使用的确切库(lodash),您可以按照您想要的确切顺序执行此操作。 我把这个过程分解为以下步骤:

第1步:对数据进行分组。 应该有一个包含所有“Bob”记录的数组,以及包含所有“Joe”记录的另一个数组等。我决定更进一步,只存储scoreTotal而不是整个记录。

第2步:循环遍历每个数组,按降序对它们进行排序,并切片到所需的“顶部”结果。

第3步:使用我们之前的调查结果过滤原始数据,如果我们有一个特定人的确切评分总匹配,则只包含结果中的记录,并且每个评分只有一次,从我们的临时数组中删除它,所以我们不要获得重复记录并返回比所需“最高”记录更多的记录。

 // The magical function function showTopResults(input, topResults) { // Step one: group like data together var groupedData = _.reduce(input, function(result, value, key) { if(typeof result[value.person] == 'undefined'){ result[value.person] = []; } result[value.person].push(value.scoreTotal); return result; }, {}); // Step two: loop through person keys, sort it, then grab only the first "x" elements _.forEach(groupedData, function(value, key) { value = value.sort(function(a,b){ var n = b - a; return n ? n < 0 ? -1 : 1 : 0}); // first element is largest groupedData[key] = value.slice(0, topResults); // we only want first x results, so we get largest only }); // Step three: filter our elements only where we have a match var filterResults = _.filter(input,function(o){ var idx = _.indexOf(groupedData[o.person],o.scoreTotal); if( idx > -1) { groupedData[o.person].splice(idx, 1); // remove element so we don't get multiple elements of equal value return true; // We have a match } else { return false; // not a match } }); return filterResults; } // Our input var input = [ { person: 'Fred', scoreTotal: 29 }, { person: 'Alice', scoreTotal: 34 }, { person: 'Alice', scoreTotal: 22 }, { person: 'Mary', scoreTotal: 14 }, { person: 'Bob', scoreTotal: 33 }, { person: 'Bob', scoreTotal: 13 }, { person: 'Bob', scoreTotal: 22 }, { person: 'Joe', scoreTotal: 28 } ]; // Tests using our magical function console.log(showTopResults(input, 1)); console.log(showTopResults(input, 2)); 
 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script> 

不完全是你问的,但值得考虑:

处理此问题的最佳方法是重新构建数据

 var people = {}, personArray = [ { person: 'Fred', scoreTotal: 29 }, { person: 'Alice', scoreTotal: 34 }, { person: 'Alice', scoreTotal: 22 }, { person: 'Mary', scoreTotal: 14 }, { person: 'Bob', scoreTotal: 33 }, { person: 'Bob', scoreTotal: 13 }, { person: 'Bob', scoreTotal: 22 }, { person: 'Joe', scoreTotal: 28 } ]; //loop person Array to group array by person //and sort their top scores from best to worst for(var i = 0; i < personArray.length; i++){ var person = personArray[i].person, score = personArray[i].scoreTotal, scores = people[person] || [], pushed = false; if(scores.length){ for(var n = 0; n < scores.length; n++){ if(score > scores[n]){ pushed = true; scores.splice(n, 0, score); break; } } } if(!pushed) scores.push(score); people[person] = scores; } console.log(people); //return top `n` scores for each person from best to worst function topScores(nScores){ var result = []; for(var name in people){ if(people.hasOwnProperty(name)){ for(var r = 0; ((r < people[name].length) && (r < nScores)); r++){ result.push({person: name, scoreTotal: people[name][r]}); } } } return result } console.log(topScores(2)) console.log(topScores(3)) console.log(topScores(1)) 

使用person prop作为键将数组减少为对象。 对于每个人添加到对象,如果键不存在或者scoreTotal大于当前scoreTotal 使用Object.values()转换回数组:

 const data = [{"person":"Fred","scoreTotal":29},{"person":"Alice","scoreTotal":34},{"person":"Alice","scoreTotal":22},{"person":"Mary","scoreTotal":14},{"person":"Bob","scoreTotal":33},{"person":"Bob","scoreTotal":13},{"person":"Bob","scoreTotal":22},{"person":"Joe","scoreTotal":28}]; const result = Object.values(data.reduce((r, p) => { if(!r[p.person] || r[p.person].scoreTotal < p.scoreTotal) { r[p.person] = p; } return r; }, {})); console.log(result); 

这不是一个完整的答案,只是一个提示。 不要使用delete array[index] ,请使用array.splice 有关详细信息,请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

下一个建议是澄清你是否真的需要修改数组,或者只是在没有原始数组数据的情况下获得一个新数组。 如果您不需要修改原始文件,最好只使用reduce之类的函数,或使用for循环有选择地将项目复制到新数组中。

使用下划线: https//underscorejs.org/

 const db = [ { person: 'Fred', scoreTotal: 29 }, { person: 'Fred', scoreTotal: 10 }, { person: 'Fred', scoreTotal: 2 }, { person: 'Alice', scoreTotal: 34 }, { person: 'Alice', scoreTotal: 5 }, { person: 'Alice', scoreTotal: 15 }, { person: 'Alice', scoreTotal: 40 }, { person: 'Mary', scoreTotal: 23 }, { person: 'Mary', scoreTotal: 32 }, { person: 'Mary', scoreTotal: 98 }, { person: 'Mary', scoreTotal: 4 }, { person: 'Bob', scoreTotal: 70 }, { person: 'Bob', scoreTotal: 65 }, { person: 'Bob', scoreTotal: 35 }, { person: 'Bob', scoreTotal: 5 }, { person: 'Joe', scoreTotal: 28 }]; const nOfItens = 2; const persons = _.map(db, item => item.person); const names = _.uniq(persons); let newList = []; for (var i = 0; names.length > i; i++) { let filter = _.filter(db, person => person.person === names[i]); let sort = _.sortBy(filter, num => -num.scoreTotal); let items = sort.splice(0, nOfItens) newList = [...newList, ...items] } console.log(newList); 
 <script src="https://underscorejs.org/underscore-min.js"></script> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM