如何在JavaScript中使用map(),reduce()和filter()简化代码库

by Alex Permyakov

通过亚历克斯·Perl米亚科夫

如何在JavaScript中使用map(),reduce()和filter()简化代码库 (How to simplify your codebase with map(), reduce(), and filter() in JavaScript)

When you read about Array.reduce and how cool it is, the first and sometimes the only example you find is the sum of numbers. This is not our definition of ‘useful’. ?

当您了解Array.reduce以及它有多酷时,您发现的第一个(有时是唯一的)示例是数字总和。 这不是我们对“有用”的定义。 ?

Moreover, I’ve never seen it in a real codebase. But, what I’ve seen a lot is 7–8 line for-loop statements for solving a regular task where Array.reduce could do it in one line.

而且,我从未在真正的代码库中看到过它。 但是,我经常看到的是7到8行的for循环语句,用于解决Array.reduce可以在一行中完成的常规任务。

Recently I rewrote a few modules using these great functions. It surprised me how simplified the codebase became. So, below is a list of goodies.

最近,我使用这些强大的功能重写了一些模块。 令我惊讶的是代码库变得如此简化。 因此,以下是好东西列表。

If you have a good example of using a map or reduce method — post it in the comments section. ?

如果您有使用mapreduce方法的好例子,请将其张贴在评论部分。 ?

Let’s get started!

让我们开始吧!

1.从数字/字符串数组中删除重复项 (1. Remove duplicates from an array of numbers/strings)

Well, this is the only one not about map/reduce/filter, but it’s so compact that it was hard not to put it in the list. Plus we’ll use it in a few examples too.

好吧,这是唯一一个与map / reduce / filter无关的方法,但是它是如此紧凑以至于很难将其放在列表中。 另外,我们还将在一些示例中使用它。

const values = [3, 1, 3, 5, 2, 4, 4, 4];
const uniqueValues = [...new Set(values)];

// uniqueValues is [3, 1, 5, 2, 4]
2.简单搜索(区分大小写) (2. A simple search (case-sensitive))

The filter() method creates a new array with all elements that pass the test implemented by the provided function.

filter()方法创建一个新数组,其中所有元素都通过了由提供的函数实现的测试。

const users = [
  { id: 11, name: 'Adam', age: 23, group: 'editor' },
  { id: 47, name: 'John', age: 28, group: 'admin' },
  { id: 85, name: 'William', age: 34, group: 'editor' },
  { id: 97, name: 'Oliver', age: 28, group: 'admin' }
];

let res = users.filter(it => it.name.includes('oli'));

// res is []
3.简单搜索(不区分大小写) (3. A simple search (case-insensitive))
let res = users.filter(it => new RegExp('oli', "i").test(it.name));

// res is
[
  { id: 97, name: 'Oliver', age: 28, group: 'admin' }
]
4.检查是否有任何用户具有管理员权限 (4. Check if any of the users have admin rights)

The some() method tests whether at least one element in the array passes the test implemented by the provided function.

some()方法测试数组中的至少一个元素是否通过了由提供的函数实现的测试。

const hasAdmin = users.some(user => user.group === 'admin');

// hasAdmin is true
5.展平数组 (5. Flattening an array of arrays)

The result of the first iteration is equal to : […[], …[1, 2, 3]] means it transforms to [1, 2, 3] — this value we provide as an ‘acc’ on the second iteration and so on.

第一次迭代的结果等于:[…[],…[1、2、3]]表示它转换为[1、2、3]-这个值在第二次迭代中作为'acc'提供,并且以此类推。

const nested = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
let flat = nested.reduce((acc, it) => [...acc, ...it], []);

// flat is [1, 2, 3, 4, 5, 6, 7, 8, 9]

We can slightly improve this code by omitting an empty array[]as the second argument for reduce(). Then the first value of the nested will be used as the initial acc value. Thanks to Vladimir Efanov.

我们可以通过省略空数组[]作为reduce()的第二个参数来稍微改善此代码 然后, 嵌套的第一个值将用作初始acc值。 感谢Vladimir Efanov

let flat = nested.reduce((acc, it) => [...acc, ...it]);

// flat is [1, 2, 3, 4, 5, 6, 7, 8, 9]

Note that using the spread operator inside a reduce is not great for performance. This example is a case when measuring performance makes sense for your use-case. ☝️

请注意,在reduce中使用散布运算符对性能并不是很好。 此示例是衡量性能对您的用例有意义的一种情况。 ☝️

Thanks to Paweł Wolak, here is a shorter way without Array.reduce:

感谢PawełWolak ,这是不使用Array.reduce的较短方法

let flat = [].concat.apply([], nested);

Also Array.flat is coming, but it’s still an experimental feature.

Array.flat也即将面世 ,但这仍然是一项实验性功能。

6.创建一个包含指定键频率的对象 (6. Create an object that contains the frequency of the specified key)

Let’s group and count the ‘age’ property for each item in the array:

让我们对数组中每个项目的'age'属性进行分组和计数:

const users = [
  { id: 11, name: 'Adam', age: 23, group: 'editor' },
  { id: 47, name: 'John', age: 28, group: 'admin' },
  { id: 85, name: 'William', age: 34, group: 'editor' },
  { id: 97, name: 'Oliver', age: 28, group: 'admin' }
];

const groupByAge = users.reduce((acc, it) => {
  acc[it.age] = acc[it.age] + 1 || 1;
  return acc;
}, {});

// groupByAge is {23: 1, 28: 2, 34: 1}

Thanks to sai krishna for suggesting this one!

感谢sai krishna建议这个!

7.索引对象数组(查找表) (7. Indexing an array of objects (lookup table))

Instead of processing the whole array for finding a user by id, we can construct an object where the user’s id represents a key (with constant searching time).

我们可以构造一个对象,其中用户的ID代表键(具有恒定的搜索时间),而不是处理整个数组以通过ID查找用户。

const uTable = users.reduce((acc, it) => (acc[it.id] = it, acc), {})

// uTable equals:
{
  11: { id: 11, name: 'Adam', age: 23, group: 'editor' },
  47: { id: 47, name: 'John', age: 28, group: 'admin' },
  85: { id: 85, name: 'William', age: 34, group: 'editor' },
  97: { id: 97, name: 'Oliver', age: 28, group: 'admin' }
}

It’s useful when you have to access your data by id like uTable[85].name a lot.

当您必须经常通过uTable[85].name类的id访问数据时,此功能很有用。

8.为数组中每个项目的给定键提取唯一值 (8. Extract the unique values for the given key of each item in the array)

Let’s create a list of existing users’ groups. The map() method creates a new array with the results of calling a provided function on every element in the calling array.

让我们创建一个现有用户组的列表。 map()方法创建一个新数组,并在调用数组中的每个元素上调用提供的函数。

const listOfUserGroups = [...new Set(users.map(it => it.group))];

// listOfUserGroups is ['editor', 'admin'];
9.对象键值映射反转 (9. Object key-value map reversal)
const cities = {
  Lyon: 'France',
  Berlin: 'Germany',
  Paris: 'France'
};

let countries = Object.keys(cities).reduce(
  (acc, k) => (acc[cities[k]] = [...(acc[cities[k]] || []), k], acc) , {});
  
// countries is
{
  France: ["Lyon", "Paris"],
  Germany: ["Berlin"]
}

This one-liner looks quite tricky. We use the comma operator here, and it means we return the last value in parenthesis — acc. Let’s rewrite this example in a more production-ready and performant way:

这种单线看上去很棘手。 我们在这里使用逗号运算符 ,这意味着我们返回括号中的最后一个值acc 。 让我们以一种更具生产就绪性和高性能的方式重写此示例:

let countries = Object.keys(cities).reduce((acc, k) => {
  let country = cities[k];
  acc[country] = acc[country] || [];
  acc[country].push(k);
  return acc;
}, {});

Here we don’t use spread operator — it creates a new array on each reduce() call, which leads to a big performance penalty: O(n²). Instead the old good push() method.

这里我们不使用散布运算符 -它在每个reduce()调用上创建一个新数组,这会导致较大的性能损失:O(n²)。 相反,旧的好push()方法

10.从摄氏值数组创建华氏值数组 (10. Create an array of Fahrenheit values from an array of Celsius values)

Think of it as processing each element with a given formula ?

将其视为使用给定公式处理每个元素?

const celsius = [-15, -5, 0, 10, 16, 20, 24, 32]
const fahrenheit = celsius.map(t => t * 1.8 + 32);

// fahrenheit is [5, 23, 32, 50, 60.8, 68, 75.2, 89.6]
11.将对象编码为查询字符串 (11. Encode an object into a query string)
const params = {lat: 45, lng: 6, alt: 1000};

const queryString = Object.entries(params).map(p => encodeURIComponent(p[0]) + '=' + encodeURIComponent(p[1])).join('&')

// queryString is "lat=45&lng=6&alt=1000"
12.仅使用指定的键将用户表打印为可读字符串 (12. Print a table of users as a readable string only with specified keys)

Sometimes you want to print your array of objects with selected keys as a string, but you realize that JSON.stringify is not that great ?

有时您想将选定键的对象数组打印为字符串,但是您意识到JSON.stringify不是那么好吗?

const users = [
  { id: 11, name: 'Adam', age: 23, group: 'editor' },
  { id: 47, name: 'John', age: 28, group: 'admin' },
  { id: 85, name: 'William', age: 34, group: 'editor' },
  { id: 97, name: 'Oliver', age: 28, group: 'admin' }
];

users.map(({id, age, group}) => `\n${id} ${age} ${group}`).join('')

// it returns:
"
11 23 editor
47 28 admin
85 34 editor
97 28 admin"

JSON.stringify can make the string output more readable, but not as a table:

JSON.stringify可以使字符串输出更具可读性,但不能作为表:

JSON.stringify(users, ['id', 'name', 'group'], 2);

// it returns:
"[
  {
    "id": 11,
    "name": "Adam",
    "group": "editor"
  },
  {
    "id": 47,
    "name": "John",
    "group": "admin"
  },
  {
    "id": 85,
    "name": "William",
    "group": "editor"
  },
  {
    "id": 97,
    "name": "Oliver",
    "group": "admin"
  }
]"
13.查找并替换对象数组中的键值对 (13. Find and replace a key-value pair in an array of objects)

Let’s say we want to change John’s age. If you know the index, you can write this line: users[1].age = 29. However, let’s take a look at another way of doing it:

假设我们想改变约翰的年龄。 如果知道索引,则可以编写以下行: users[1].age = 29 。 但是,让我们看一下另一种方法:

const updatedUsers = users.map(
  p => p.id !== 47 ? p : {...p, age: p.age + 1}
);

// John is turning 29 now

Here instead of changing the single item in our array, we create a new one with only one element different. Now we can compare our arrays just by reference like updatedUsers == users which is super quick! React.js uses this approach to speed up the reconciliation process. Here is an explanation.

在这里,我们无需更改数组中的单个项目,而是创建一个只有一个元素不同的新项目。 现在我们可以通过引用比较我们的数组,例如updatedUsers == users ,这非常快! React.js使用这种方法来加速对帐过程。 这是一个解释。

14.数组的并集(A∪B) (14. Union (A ∪ B) of arrays)

Less code than importing and calling the lodash method union.

比导入和调用lodash方法union更少的代码。

const arrA = [1, 4, 3, 2];
const arrB = [5, 2, 6, 7, 1];

[...new Set([...arrA, ...arrB])]; // returns [1, 4, 3, 2, 5, 6, 7]
15.数组的交集(A∩B) (15. Intersection (A ∩ B) of arrays)

The last one!

最后一个!

const arrA = [1, 4, 3, 2];
const arrB = [5, 2, 6, 7, 1];

arrA.filter(it => arrB.includes(it)); // returns [1, 2]

As an exercise try to implement difference (A \ B) of the arrays. Hint: use an exclamation mark.

作为练习,请尝试实现数组的差异(A \ B)。 提示:使用感叹号。

Thanks to Asmor and incarnatethegreat for their comments about #9.

感谢Asmorincarnatethegreat对#9的评论。

而已! (That’s it!)

If you have any questions or feedback, let me know in the comments down below or ping me on Twitter.

如果您有任何疑问或反馈,请在下面的评论中让我知道,或者在Twitter上 ping我。

如果这有用,请单击拍手? 请点击以下几次以显示您的支持! ???? (If this was useful, please click the clap ? button down below a few times to show your support! ⬇⬇ ??)

Here are more articles I’ve written:

这是我写的更多文章:

How to get started with internationalization in JavaScriptBy adapting our app for different languages and countries, we provide a better user experience. It’s simpler for users…

如何开始使用JavaScript进行国际化 通过将我们的应用程序适应不同的语言和国家/地区,我们可以提供更好的用户体验。 对用户来说更简单...

Production ready Node.js REST APIs Setup using TypeScript, PostgreSQL and Redis.A month ago I was given a task to build a simple Search API. All It had to do is to grab some data from 3rd party…

使用TypeScript,PostgreSQL和Redis的可用于生产环境的Node.js REST API设置。 一个月前,我接到了构建简单Search API的任务。 它所要做的就是从第三方那里获取一些数据…

Thanks for reading ❤️

感谢您阅读❤️

翻译自: https://www.freecodecamp.org/news/15-useful-javascript-examples-of-map-reduce-and-filter-74cbbb5e0a1f/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值