使用 lodash(或 vanilla javascript)对对象数组进行排序和过滤

sort and filter an object array with lodash (or vanilla javascript)

我有这个对象,我想通过按对象仅保留 2 个最高值来排序和过滤。

obj={ A :[{
      asset: 9,
      biodiversity: 4,
      infrastructure: 15,
      deflation: 11,
      energy: 9
    }],
  B:[{
      asset: 12,
      biodiversity: 10,
      infrastructure: 9,
      deflation: 7,
      energy: 15
    }],
  C:[{
      asset: 2,
      biodiversity: 12,
      infrastructure: 6,
      deflation: 6,
      energy: 8
    }]}

我想按对象的值对对象进行排序,并过滤掉最高的 2 个,例如:

{A :[{
      infrastructure: 15,
      deflation: 11
    }],
  B:[{
      energy: 15,
      asset: 12
    }],
  C:[{
      biodiversity: 12,
      energy: 8
    }]}

我试过这个排序:

Object.keys(obj).forEach((a) => _.sortBy(obj[a][0])))

但这显然是错误的。 我正在使用 lodash,但也会接受香草 javascript 解决方案。

您可以获取内部对象的条目并按值降序排序,获取前两个 key/value 对并从中构建一个新对象。

const
    data = { A: [{ asset: 9, biodiversity: 4, infrastructure: 15, deflation: 11, energy: 9 }], B: [{ asset: 12, biodiversity: 10, infrastructure: 9, deflation: 7, nergy: 15 }], C: [{ asset: 2, biodiversity: 12, infrastructure: 6, deflation: 6, energy: 8 }]},
    result = Object.fromEntries(Object
        .entries(data)
        .map(([k, a]) => [k, a.map(o => Object.fromEntries(Object
            .entries(o)
            .sort((a, b) => b[1] - a[1])
            .slice(0, 2)
        ))])
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

(Edit/Note:这是基于您最初发布的代码。很高兴看到您更新了问题并去掉了包装数组。)

这是一个相对实用的方法。

secondLargestValue 函数查找每个对象内的阈值。 copyWithoutValsBelowThreshold 函数为我们提供了对象的修改副本。

我们遍历 top-level 对象中的条目并应用这两个函数。 请参阅代码中的注释以进一步说明。

let json = getArray(); // Identifies the original array

// Defines `secondLargestVal` function
const secondLargestVal = someObj =>

  // Gets second item of array after sorting numerically in descending order
  Object.values(someObj).sort((a, b) => b - a)[1];

// Defines `copyWithoutValsBelowThreshold` function
const copyWithoutValsBelowThreshold = ( (someObj, threshold) => {

  // This function doesn't mutate the original value
  clone = Object.assign({}, someObj); // Copies obj
  for(let prop in clone){

    // Loops through properties, deleting non-qualifying ones
    if(clone[prop] < threshold){
      delete clone[prop];
    }
  }
  return clone;
});


// Defines our main function
const mutateJson = () => {
  let entries = Object.entries(json[0]);

  entries = entries.map(entry => {
    // `entry[0]` is the property name (eg: 'A') -- we don't actually use this
    // `entry[1]` is the value (in this case, an array containing a single object)
    let obj = entry[1][0]; // Identifies the actual object
    const threshold = secondLargestVal(obj); // Identifies minimum value
    
    // Updates the entry, deleting properties whose values are too low
    entry[1][0] = copyWithoutValsBelowThreshold(obj, threshold);
    return entry;
  });

  json[0] = Object.fromEntries(entries); // Replaces the top-level object
}


// Calls the main function
mutateJson();
console.log(json);


// Provides the original array
function getArray(){
  return [{ A :[{
      asset: 9,
      biodiversity: 4,
      infrastructure: 15,
      deflation: 11,
      energy: 9
    }],
  B:[{
      asset: 12,
      biodiversity: 10,
      infrastructure: 9,
      deflation: 7,
      energy: 15
    }],
  C:[{
      asset: 2,
      biodiversity: 12,
      infrastructure: 6,
      deflation: 6,
      energy: 8
    }]}]
}