从数组中过滤数据的最佳方法

Best Approach to filter out data from array

我想根据特定条件过滤掉数组中的数据。

检查 'isChecked' 和 'isPrimaryKey' 是否为真,如果 'rename' 不为空,则在输出数组中需要显示重命名,否则显示名称。

下面的代码非常适合我。我想知道有没有更好的方法。

还想知道这种方法有什么问题吗(使用 map 迭代有限数量的对象)

let columnList = [
  { id:1, name: "Id", rename: "", isChecked: true, isPrimaryKey: true },
  { id:2, name: "Name", isChecked: false, isPrimaryKey: true },
  { id:3, name: "age",  rename: "Age", isChecked: true, isPrimaryKey: true },
  { id:4, name: "Designation", isChecked: true, isPrimaryKey: false },
  { id:5, name: "Salary", isChecked: false, isPrimaryKey: true },
  { id:6, name: "Department", isChecked: true, isPrimaryKey: false },
  { id:7, name: "Project", isChecked: false, isPrimaryKey: false }
];

let data = columnList.map(d => {
  if(d.isChecked && d.isPrimaryKey) {
    return (d.rename && d.rename !== '') ? d.rename : d.name;
  }
});

data = data.filter(item => item);
console.log(data);

Output: ["Id", "Age"]

您应该使用 array.reduce 而不是 array.map + array.filter

  • Array.map - 此函数将 return 一个 n 元素的数组,其值为 return。它可以 return partial/processed 值。
  • Array.filter - 此函数用于过滤数组中的项目。这将 return n 个匹配大小写的元素,但不会 change/process 它们。
  • Array.reduce - 此函数旨在减少数组中的项目数。在这样做时,您可以操纵项目和 return 自定义值。

另外,对于需要检查 rename 是否可用然后 return 否则 return name 的情况,您可以使用 .push(d.rename || d.name)

let columnList = [
  { id:1, name: "Id", rename: "", isChecked: true, isPrimaryKey: true },
  { id:2, name: "Name", isChecked: false, isPrimaryKey: true },
  { id:3, name: "age",  rename: "Age", isChecked: true, isPrimaryKey: true },
  { id:4, name: "Designation", isChecked: true, isPrimaryKey: false },
  { id:5, name: "Salary", isChecked: false, isPrimaryKey: true },
  { id:6, name: "Department", isChecked: true, isPrimaryKey: false },
  { id:7, name: "Project", isChecked: false, isPrimaryKey: false }
];

let data = columnList.reduce((p, d) => {
  if(d.isChecked && d.isPrimaryKey) {
    p.push(d.rename || d.name);
  }
  return p;
}, []);
console.log(data)

但如果您仍然希望选择 Array.map + array.filter,您可以尝试这样的操作:

let columnList = [
  { id:1, name: "Id", rename: "", isChecked: true, isPrimaryKey: true },
  { id:2, name: "Name", isChecked: false, isPrimaryKey: true },
  { id:3, name: "age",  rename: "Age", isChecked: true, isPrimaryKey: true },
  { id:4, name: "Designation", isChecked: true, isPrimaryKey: false },
  { id:5, name: "Salary", isChecked: false, isPrimaryKey: true },
  { id:6, name: "Department", isChecked: true, isPrimaryKey: false },
  { id:7, name: "Project", isChecked: false, isPrimaryKey: false }
];

let data = columnList
  .filter(d => d.isChecked && d.isPrimaryKey)
  .map(d => d.rename || d.name);

console.log(data)

区别在于阅读。当你读它的时候,你读它是,

You are filtering list by isChecked and isPrimaryKey and the from the filtered, you are returning either rename or name

这些函数是函数式编程的一部分,它们的美在于提高代码的可读性。在您的代码中,reader 将必须阅读逻辑以了解您要实现的目标,这超出了目的。

Rajesh 回答的后续:如果您想要 filter-then-map 的干净代码,但不想添加额外的迭代,Ramda 提供对 transducers in many of its list-handling functions, including map and filter。以下版本将迭代列表一次,检查每一步是否项目匹配过滤器,以及是否通过传递给 map.

的函数选择正确的 属性

但是代码仍然很好地融入了过滤步骤和映射步骤。

let columnList = [
  { id:1, name: "Id", rename: "", isChecked: true, isPrimaryKey: true },
  { id:2, name: "Name", isChecked: false, isPrimaryKey: true },
  { id:3, name: "age",  rename: "Age", isChecked: true, isPrimaryKey: true },
  { id:4, name: "Designation", isChecked: true, isPrimaryKey: false },
  { id:5, name: "Salary", isChecked: false, isPrimaryKey: true },
  { id:6, name: "Department", isChecked: true, isPrimaryKey: false },
  { id:7, name: "Project", isChecked: false, isPrimaryKey: false }
];


const getCols = R.into([], R.compose(
  R.filter(d => d.isChecked && d.isPrimaryKey),
  R.map(d => d.rename || d.name)
))

const cols = getCols(columnList)

console.log(cols)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

您还询问了您的方法是否存在问题。可能有。除了已经讨论过的额外迭代之外,还有两个问题:首先,将 filteritem => item 一起使用不仅会禁止 null/undefined 值,还会禁止任何 false -y 值,最显着的是 0。因此,如果您尝试提取一个列表,其中 0 可能是一个合理的值,这将排除它。其次,在函数式编程中,重新分配变量通常被认为是一种坏习惯。所以 data = data.filter(...) 很不受欢迎。