Map and set about iteration

We have learned about the following complex data structures:

But this is not enough to deal with the reality. This is why there are maps and sets.

Map

A map is a collection of data items with keys, just like an object. But their biggest difference is that map allows any type of key.

Its methods and properties are as follows:

for instance:

let map = new Map();

map.set('1','str1');   // 字符串键
map.set(1,'num1');     // 数字键
map.set(true,'bool1'); // 布尔值键

// 还记得普通的 Object 吗? 它会将键转化为字符串
// Map 则会保留键的类型,所以下面这两个结果不同:
alert( map.get(1)   ); // 'num1'
alert( map.get('1') ); // 'str1'

alert( map.size ); // 3

As we can see, unlike objects, keys are not converted to strings. Keys can be of any type.

Map [key] is not the correct way to use map

Although map [key] is also valid, for example, we can set map [key] = 2, which will treat map as a plain object of JavaScript, so it implies all corresponding restrictions (no object key, etc.).

So we should use map methods: set, get, etc.

Map can also use objects as keys.

For example:

let john = { name: "John" };

// 存储每个用户的来访次数
let visitsCountMap = new Map();

// john 是 Map 中的键
visitsCountMap.set(john,123);

alert( visitsCountMap.get(john) ); // 123

Using objects as keys is one of the most noteworthy and important functions of map. For string keys, object (ordinary object) can also be used normally, but not for object keys.

Let's try:

let john = { name: "John" };

let visitsCountObj = {}; // 尝试使用对象

visitsCountObj[john] = 123; // 尝试将 john 对象作为键

// 是写成了这样!
alert( visitsCountObj["[object Object]"] ); // 123

Because visitscountobj is an object, it will convert all keys such as John into a string, so we get the string key "[object object]". This is obviously not the result we want.

How does map compare keys?

Map uses the samevaluezero algorithm to compare keys for equality. It is similar to strictly equal to = = =, but the difference is that Nan is regarded as equal to Nan. So Nan can also be used as a key.

This algorithm cannot be changed or customized.

call chaining

Each time map All set calls will return the map itself, so we can make "chain" calls:

map.set('1','str1')
  .set(1,'num1')
  .set(true,'bool1');

Map iteration

If you want to use loops in a map, you can use the following three methods:

For example:

let recipeMap = new Map([
  ['cucumber',500],['tomatoes',350],['onion',50]
]);

// 遍历所有的键(vegetables)
for (let vegetable of recipeMap.keys()) {
  alert(vegetable); // cucumber,tomatoes,onion
}

// 遍历所有的值(amounts)
for (let amount of recipeMap.values()) {
  alert(amount); // 500,350,50
}

// 遍历所有的实体 [key,value]
for (let entry of recipeMap) { // 与 recipeMap.entries() 相同
  alert(entry); // cucumber,500 (and so on)
}

Use insert order

The order of iterations is the same as the order in which values are inserted. Unlike ordinary objects, map retains this order.

In addition, map has a built-in foreach method, which is similar to array:

// 对每个键值对 (key,value) 运行 forEach 函数
recipeMap.forEach( (value,key,map) => {
  alert(`${key}: ${value}`); // cucumber: 500 etc
});

Object. Entries: create a map from an object

After creating a map, we can pass in an array with key value pairs (or other iteratable objects) for initialization, as shown below:

// 键值对 [key,value] 数组
let map = new Map([
  ['1','str1'],[1,'num1'],[true,'bool1']
]);

alert( map.get('1') ); // str1

If we want to create a map from an existing plain object, we can use the built-in method object.entries (obj), which returns an array of key / value pairs of the object. The format of the array is completely in accordance with the format required by the map.

So you can create a map from an object as follows:

let obj = {
  name: "John",age: 30
};

let map = new Map(Object.entries(obj));

alert( map.get('name') ); // John

Here, object Entries returns an array of key / value pairs: ["name", "John"], ["age", 30]]. This is the format required for map.

Object. Fromentries: create objects from map

We have just learned how to use object Entries (obj) creates a map from a plain object.

Object. The fromentries method has the opposite effect: given an array with [key, value] key value pairs, it will create an object based on the given array:

let prices = Object.fromEntries([
  ['banana',1],['orange',2],['meat',4]
]);

// 现在 prices = { banana: 1,orange: 2,meat: 4 }

alert(prices.orange); // 2

We can use object Fromentries gets a plain object from the map.

For example, we store some data in the map, but we need to pass this data to the third-party code that needs plain objects.

Let's start:

let map = new Map();
map.set('banana',1);
map.set('orange',2);
map.set('meat',4);

let obj = Object.fromEntries(map.entries()); // 创建一个普通对象(plain object)(*)

// 完成了!
// obj = { banana: 1,meat: 4 }

alert(obj.orange); // 2

Call map Entries () will return an iteratable key / value pair, which happens to be object The required format for fromentries.

We can make the line with (*) shorter:

let obj = Object.fromEntries(map); // 省掉 .entries()

The function of the above code is the same, because object Fromentries expects an iteratable object as a parameter, not necessarily an array. And the standard iteration of map will return the same as map The same key / value pair as entries(). Therefore, we can obtain a plain object with the same key / value pair as the map.

Set

Set is a special type collection - "collection of values" (no key), and each value can only appear once.

Its main methods are as follows:

Its main feature is that set is called repeatedly with the same value Add (value) does not change. This is why each value in set only appears once.

For example, we have guests visiting, and we want to remember each of them. However, if a guest who has already visited visits again, it shall not cause duplicate records. Each visitor must be "counted" only once.

Set can help us solve this problem:

let set = new Set();

let john = { name: "John" };
let pete = { name: "Pete" };
let mary = { name: "Mary" };

// visits,一些访客来访好几次
set.add(john);
set.add(pete);
set.add(mary);
set.add(john);
set.add(mary);

// set 只保留不重复的值
alert( set.size ); // 3

for (let user of set) {
  alert(user.name); // John(然后 Pete 和 Mary)
}

An alternative to set can be a user array that uses arr.find to check for duplicates each time a value is inserted. However, this performance will be poor, because this method will traverse the entire array to check each element. Set optimizes the uniqueness check better.

Set iteration

We can use for Of or foreach to traverse the set:

let set = new Set(["oranges","apples","bananas"]);

for (let value of set) alert(value);

// 与 forEach 相同:
set.forEach((value,valueAgain,set) => {
  alert(value);
});

Pay attention to an interesting thing. The callback function for each has three parameters: a value, then the same value valueagain, and finally the target object. Yes, the same value appears twice in the parameter.

The callback function of foreach has three parameters for compatibility with map. Of course, it does seem strange. However, it is helpful to easily replace map with set in specific cases, and vice versa.

The methods used for iteration in map are also supported in set:

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>