c++ map用值寻找键
The verbosity and elegance of a solution are driven by the tools we have to solve a particular problem. While the goal of problem-solving is to solve a problem, it’s methods should move towards the most elegant way possible. The journey towards such a solution, however, seems to lie on an asymptotic curve. Perfection gets closer and closer but forever remains out of reach.
解决方案的冗长性和优雅性是由我们用来解决特定问题的工具所驱动的。 解决问题的目标是解决问题 ,但它的方法应朝着最优雅的方式发展。 但是,寻求这种解决方案的过程似乎在于渐近曲线。 完美越来越近,但永远都遥不可及。
问题 (The Problem)
Imagine having an array and needing to change each element in the array. Maybe, for example, taking an array of heights in inches and needing to convert them to centimeters. Or possibly converting an array of temperatures in Celcius to Fahrenheit. If you are new to programming, your mind might immediately go to some form of a loop. And, guess what? I’m sure you could make it work.
假设有一个数组,需要更改数组中的每个元素。 例如,也许以英寸为单位获取高度数组,并需要将其转换为厘米。 或者可能将摄氏温度的一系列温度转换为华氏温度。 如果您不熟悉编程,则可能会立即陷入某种形式的循环。 你猜怎么着? 我确定您可以使它正常工作。
However, I am here to give you one more tool — something to get you just a little closer to elegant: Array.prototype.map()
.
但是,我在这里为您提供了另外一个工具— Array.prototype.map()
使您更接近优雅。
The map
method allows us to transform each element of an array, without affecting the original array. It’s considered a higher-order function and a functional-programming technique because it takes a function as an argument and we are performing computation without mutating the state of our application.
map
方法使我们能够变换数组的每个元素,而不会影响原始数组。 它被认为是高阶函数和函数编程技术,因为它以函数为参数,并且我们在不改变应用程序状态的情况下执行计算。
Map
is a property that is inherited from the array prototype. Prototypes provide built-in-methods that objects come with (arrays are special types of objects in the eyes of JavaScript). Whilemap
may be a little more foreign, this prototype is no different than, for example, theArray.length
prototype. These are simply methods that are baked into JavaScript. Array prototypes can be added and mutated by:Array.prototype.<someMethodHere>
= ...
Map
是从数组原型继承的属性。 原型提供了对象附带的内置方法(数组在JavaScript中是对象的特殊类型)。 虽然map
可能更陌生,但此原型与Array.length
原型没有什么不同。 这些只是烘焙到JavaScript中的方法。 数组原型可以通过以下方式添加和变异:Array.prototype.<someMethodHere>
= ...
By the end of this lesson, we will discover how map
works and write our own array prototype method.
在本课程结束时,我们将发现map
工作原理并编写我们自己的数组原型方法。
那么.map()有什么作用? (So what does .map() do?)
Let’s say you have an array of temperatures in Celsius that you want to convert to Fahrenheit.
假设您要转换为华氏度时有一系列摄氏温度。
There are a number of ways to solve this problem. One way may be to write a for
loop to create an array of Fahrenheit temperatures from the given Celsius temperatures.
有很多方法可以解决此问题。 一种方法可能是编写一个for
循环,以根据给定的摄氏温度创建华氏温度数组。
With the for
loop we might write:
使用for
循环,我们可以这样写:
const celciusTemps = [22, 36, 71, 54];
const getFahrenheitTemps = (function(temp) {
const fahrenheitTemps = [];
for (let i = 0; i < celciusTemps.length; i += 1) {
temp = celciusTemps[i] * (9/5) + 32
fahrenheitTemps.push(temp);
}
console.log(fahrenheitTemps); [71.6, 96.8, 159.8, 129.2
})();
A couple things to note:
需要注意的几件事:
- It works. 有用。
- We use an Immediately Invoked Function Expression (IIFE) to avoid also having to call the function. 我们使用立即调用函数表达式(IIFE)来避免也不必调用该函数。
- It’s a bit verbose and not very elegant. 这有点冗长,也不是很优雅。
Map
allows us to take the above code and refactor it to the following:
Map
允许我们采用以上代码并将其重构为以下代码:
const fahrenheitTemps = celciusTemps.map(e => e * (9/5) + 32);
console.log(fahrenheitTemps); // [71.6, 96.8, 159.8, 129.2]
那么地图如何工作? (So how does map work?)
Map
takes a function and applies that function to each element in the array. We could write map
a bit more verbose with ES5 to see this a bit more clearly.
Map
接受一个函数并将该函数应用于数组中的每个元素。 我们可以使用ES5编写更详细的map
,以便更清楚地看到这一点。
const fahrenheitTemps = celciusTemps
.map(function(elementOfArray) {
return elementOfArray * (9/5) + 32;
});
console.log(fahrenheitTemps); // [71.6, 96.8, 159.8, 129.2]
If our map function could say what it is doing, it would say:
如果我们的地图功能可以说出它在做什么,它会说:
“For every element in the array, I multiply it by (9/5), then add 32. When that is done, I return the result as an element in a new array called fahrenheitTemps.”
“对于数组中的每个元素,我将其乘以(9/5),然后加32。完成后,我将结果作为新数组中的元素返回,称为fahrenheitTemps。”
Let’s look at a more common use case. Let’s assume we have an array of people
objects. Each object has a name
and age
key-value-pair. We want to create a variable that is just the names of everyone in the array. With our for
loop method we might write:
让我们看一个更常见的用例。 假设我们有一系列people
对象。 每个对象都有一个name
和age
键值对。 我们想创建一个变量,它只是数组中每个人的名字。 使用我们的for
循环方法,我们可以编写:
const people = [
{name: Steve, age: 32},
{name: Mary, age: 28},
{name: Bill, age: 41},
];
const getNames = (function(person) {
const names = [];
for (let i = 0; i < people.length; i += 1) {
name = people[i].name;
names.push(name);
}
console.log(names); // [Steve, Mary, Bill];
})();
With map
:
有map
:
const names = people.map(e => e.name);
console.log(names) // [Steve, Mary, Bill];
Notice here we don’t transform anything, we simply return the key-value-pair name
.
请注意,这里我们不进行任何转换,只返回键值对name
。
Again, the for
loops works. But, it is verbose, and we have to create a new custom function every time we want to do a different transformation. A principal part of programming is writing DRY code (Don’t Repeat Yourself). These higher-order functions such as map, allows us to do more complex programming in fewer lines of code than we could without them.
再次, for
循环起作用。 但是,它很冗长,每次我们要执行不同的转换时,我们都必须创建一个新的自定义函数。 编程的主要部分是编写DRY代码(不要重复自己)。 这些高阶函数(例如map)使我们能够以更少的代码行进行更复杂的编程,这比没有它们的情况要多。
重新发明轮子: (Reinventing the wheel:)
To better understand what is happening under the hood, we will make our own map function that we will attach to the array prototype.
为了更好地了解幕后情况,我们将制作自己的map函数,并将其附加到数组原型。
First, to attach a prototype method to an Array, we will write:
首先,将原型方法附加到数组,我们将编写:
Array.prototype.<yourMethodHere>
Array.prototype.<yourMethodHere>
so for us:
所以对我们来说:
Array.prototype.myMap = <our code>
Array.prototype.myMap = <our code>
But, what will our code be?
但是,我们的代码将是什么?
We already have the logic we need from the for
loops above. All we need to do is refactor it a bit. Let’s refactor the last function we wrote getNames()
.
从上面的for
循环中,我们已经有了所需的逻辑。 我们需要做的只是对其进行重构。 让我们重构最后编写的函数getNames()
。
Remember, this function took a person (in other words an element of our array), did a custom transformation to that element (with the for
loop and some logic), and returned an array of names (or a new array).
记住,此函数需要一个人(换句话说,就是数组的一个元素),对该元素进行了自定义转换(带有for
循环和一些逻辑),然后返回了一个名称数组(或一个新数组)。
const getNames = (function(person) {
const names = [];
for (let i = 0; i < people.length; i += 1) {
name = people[i].name;
names.push(name);
}
console.log(names); // [Steve, Mary, Bill];
})();
First, let’s change the name of our function. After all, this new method doesn’t assume to know what kind of array it will be acting upon:
首先,让我们更改函数的名称。 毕竟,这种新方法并不假定知道要对哪种数组进行操作:
const myMap = (function(person) { //Changed name
const names = [];
for (let i = 0; i < people.length; i += 1) {
name = people[i].name;
names.push(name);
}
console.log(names); // [Steve, Mary, Bill];
})();
Second, we are creating our own version of .map()
. We know this will take a function that the user provides. Let’s change the parameter our function takes:
其次,我们创建自己的.map()
版本。 我们知道这将采用用户提供的功能。 让我们更改函数使用的参数:
// It is a bit verbose, but a very clear parameter name
const myMap = (function(userProvidedFunction) {
const names = [];
for (let i = 0; i < people.length; i += 1) {
name = people[i].name;
names.push(name);
}
console.log(names); // [Steve, Mary, Bill];
})();
Finally, we have no idea what array this method will act on. So, we can’t refer to people.length
but we can refer to this.length
. this
, will return the array the method is acting on. Also, let's clean up some of the other variable names:
最后,我们不知道此方法将作用于什么数组。 所以,我们不能引用people.length
但我们可以参考this.length
。 this
,将返回方法所作用的数组。 另外,让我们清理一些其他变量名称:
const myMap = (function(userProvidedFunction) {
// change variable name
const newArr = [];
// use "this.length"
for (let i = 0; i < this.length; i += 1) {
// use "this[i]", and change variable name
const newElement = this[i];
// update the array we push into
newArr.push(newElement);
}
// Return the newly created array
return newArr;
})();
We’re almost there, but there is one thing we are forgetting. We haven’t transformed the array! All we’ve done above is return the old array. We have to apply the user-provided function to each element of the array:
我们快到了,但是有一件事我们忘记了。 我们还没有改变阵列! 上面我们所做的就是返回旧数组。 我们必须将用户提供的函数应用于数组的每个元素:
const myMap = (function(userProvidedFunction) {
const newArr = [];
for (let i = 0; i < this.length; i += 1) {
/* Transform the element by passing it into the
* user-provided function
*/
const newElement = userProvidedFunction(this[i]);
newArr.push(newElement);
}
return newArr;
})();
Finally, we can attach our new function toArray.prototype
.
最后,我们可以将新函数附加到Array.prototype
。
Array.prototype.myMap = myMap;
Array.prototype.myMap = myMap;
A final sanity check:
最终的健康检查:
const myArray = [1, 2, 3];
// Multiply each element x 2
const myMappedArray = myArray.myMap(e => e * 2)
console.log(myMappedArray) // [2, 4, 6];
摘要 (Summary)
Map
is a prototype method offered by arrays. Behind the scenes, it iterates through the array, applying a user-provided function to each element. Ultimately, it returns a new array with the transformed values. It does this without mutating the original array. Because the parameter it takes is a function, it is considered a higher-order function. In addition, its use falls into the functional programming paradigm.
Map
是数组提供的原型方法。 在幕后,对数组进行迭代,对每个元素应用用户提供的功能。 最终,它将返回具有转换后的值的新数组。 它无需更改原始数组即可做到这一点。 因为它采用的参数是一个函数,所以它被视为高阶函数。 另外,它的使用属于功能编程范例。
Thanks for reading!
谢谢阅读!
woz
沃兹
翻译自: https://www.freecodecamp.org/news/finding-your-way-with-map-aecb8ca038f6/
c++ map用值寻找键