Ты сделал
Всякий раз, когда я иду изучать ES6, я не могу не открыть урок учителя Руан Ифэн.«Введение в ES6»Чтобы учиться и находить применение, я считаю, что большинство студентов читали статьи, написанные г-ном Жуаном, как и я.
Конечно, все также знают, что в ES6 обычно используется столько-то API, не больше и не меньше, и он как раз подходит для использования в проектах.
Но каждый раз, когда я читаю главу о структурах данных Set и Map, я всегда чувствую себя немного подавленным, потому что не понимаю цели и значения реализации такой структуры данных.
Основные сценарии применения Set и Map:Дедупликация массиваа такжехранилище данных, К счастью, прочитав книги по структурам данных и алгоритмам, я вдруг осознал открытие
Оказывается, Set — это метод, называемыйсобиратьСтруктура данных. Карта — это тип структуры данных, называемыйСловарьструктура данных
Затем следуйте за мной, чтобы узнать об этих двух структурах данных, и, наконец, самостоятельно реализовать Set и Map в ES6.
собирать
- Набор состоит из набора неупорядоченных и уникальных (то есть не повторяющихся) элементов, которые можно представить как массив без повторяющихся элементов и понятия порядка.
- ES6 предоставляет новую структуру данных Set. Он похож на массив, но все значения членов уникальны и нет повторяющихся значений.
- Сам Set является конструктором, который генерирует структуру данных Set.
- Набор, упомянутый здесь, на самом деле является набором, о котором мы говорим.Давайте сначала посмотрим на основное использование.
const s = new Set();
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));
for (let i of s) {
console.log(i); // 2 3 5 4
}
// 去除数组的重复成员
let array = [1,2,1,4,5,3];
[...new Set(array)] // [1, 2, 4, 5, 3]
Если конкретное использование все еще неясно, я объясню это подробно здесь. Теперь давайте взглянем на коллекцию, основанную на классе Set (структуре данных) в ES6.
Свойства и методы экземпляров Set
- Свойства набора:
- размер: возвращает количество элементов, содержащихся в коллекции
- Установить метод:
- Как работать
- add(value): добавить новый элемент в коллекцию
- Удалить (значение): удаление из набора значений
- has(value): возвращает true, если значение существует в коллекции, иначе false
- clear(): удаляет все элементы из коллекции
- метод обхода
- keys(): возвращает массив, содержащий все ключи в коллекции.
- values(): возвращает массив, содержащий все значения в коллекции
- записи: возвращает массив, содержащий все пары ключ-значение в коллекции (если он кажется бесполезным, он не будет реализован)
- foreach (): используется для выполнения операции на заданных элементах, отсутствие возврата
- Как работать
создать коллекцию
function Set(arr = []) { // 可以传入数组
let items = {};
this.size = 0; // 记录集合中成员的数量
}
module.exports = Set;
Здесь объект {} используется для представления коллекции, в том числе потому, что объект не позволяет ключу указывать на два разных свойства, гарантируя, что элементы в коллекции уникальны.
Далее вам нужно добавить несколько коллекций в соответствии с реализацией класса Set в ES6.Как работатьохватывать
имеет метод
Первое, что нужно реализовать, это метод has, потому что он будет вызываться в других методах, таких как add и delete.Давайте посмотрим на его реализацию.
function Set() {
let items = {};
this.size = 0;
// has(val)方法
this.has = function(val) {
// 对象都有hasOwnProperty方法,判断是否拥有特定属性
return items.hasOwnProperty(val);
};
}
добавить метод
Далее реализуем метод добавления
// add(val)方法
this.add = function(val) {
if (!this.has(val)) {
items[val] = val;
this.size++; // 累加集合成员数量
return true;
}
return false;
};
Для данного val можно определить, существует ли он в коллекции.
- Если он не существует, добавьте его в коллекцию и верните true
- Если он существует, верните false напрямую и ничего не делайте
удалить и очистить методы
Продолжайте писать, на этот раз пишите оба
// delete(val)方法
this.delete = function(val) {
if (this.has(val)) {
delete items[val]; // 将items对象上的属性删掉
this.size--;
return true;
}
return false;
};
// clear方法
this.clear = function() {
items = {}; // 直接将集合赋一个空对象即可
this.size = 0;
};
В методе удаления определить, существует ли val в коллекции, если она существует, удалить ее непосредственно из коллекции и вернуть true
Все вышеперечисленное сделаноКак работать, давайте реализуем это сноваметод обхода
ключи, метод значений
Мы можем реализовать эти два метода вместе, потому что соответствующие методы могут быть легко реализованы через расширение объекта ES6. Давайте взглянем на конкретную реализацию и приведенный выше код:
// keys()方法
this.keys = function() {
return Object.keys(items); // 返回遍历集合的所有键名的数组
};
// values()方法
this.values = function() {
return Object.values(items); // 返回遍历集合的所有键值的数组
};
используй это
// set.js
const Set = require('./Set.js'); // 导入写好的Set类
let set = new Set();
set.add(1);
set.add(3);
set.add(2);
console.log(set.keys()); // [ '1', '2', '3' ]
console.log(set.values()); // [ 1, 2, 3 ]
Здесь мы видим, что он немного отличается от Set в ES6, потому что эти методы Object представляют собой массивы, которые перебираются в соответствии с числовым значением, от малого к большому, поэтому все знают, что это лучше, конкретная реализация все же несколько отличается , ха-ха
forEach метод
Метод forEach для экземпляра структуры Set в ES6 на самом деле очень похож на метод forEach для массива, за исключением того, что имя ключа структуры Set является значением ключа, поэтому значения первого параметра и второго параметра равны всегда одно и то же
Далее мы завершим метод forEach Set в соответствии с методом forEach, реализующим массив.
// forEach(fn, context)方法
this.forEach = function(fn, context = this) {
for (let i = 0; i < this.size; i++) {
let item = Object.keys(items)[i];
fn.call(context, item, item, items);
}
};
Используйте метод forEach
// set.js
const Set = require('./Set.js');
let set = new Set();
set.add(1);
set.add(4);
set.add('3');
set.forEach((value, key) => console.log(key + ' : ' + value)); // 1:1, 3:3, 4:4
let arr = set.values(); // [ 1, 3, 4 ]
arr = new Set(arr.map(x => x * 2)).values();
console.log(arr); // [ 2, 6, 8 ]
В основном реализован метод структуры Set.Однако я обнаружил проблему,то есть писать так каждый раз при добавлении элемента действительно хлопотно.Set может принимать в качестве параметра массив,поэтому реализуем это как хорошо.
function Set(arr = []) { // 传入接受的数组,如果没有传指定一个空数组做为初始值
let items = {};
this.size = 0;
// has方法
this.has = function (val) {
return items.hasOwnProperty(val);
};
// add方法
this.add = function (val) {
// 如果没有存在items里面就可以直接写入
if (!this.has(val)) {
items[val] = val;
this.size++;
return true;
}
return false;
};
arr.forEach((val, i) => { // 遍历传入的数组
this.add(val); // 将数组里每一项值添加到集合中
});
// 省略...
}
Давайте посмотрим, сможем ли мы теперь поддерживать входящие массивы
// 间接使用map和filter
const Set = require('./Set.js');
let arr = new Set([1, 2, 3]).values();
m = new Set(arr.map(x => x * 2));
f = new Set(arr.filter(x => x>1));
console.log(m.values()); // [ 2, 4, 6 ]
console.log(f.values()); // [ 2, 3 ]
// 数组去重
let arr2 = new Set([3, 5, 2, 1, 2, 5, 5]).values();
console.log(arr2); // [ 1, 2, 3, 5 ]
Теперь у нас есть очень похожая реализация класса Set, что и в ES6. Как упоминалось ранее, массивы также можно использовать вместо объектов для хранения элементов. Студенты, которым нравятся практические занятия, вы также можете попробовать позже.
Кроме того, Set также может реализовывать объединение, пересечение и разность.
Нам еще предстоит сделать полный набор вещей, давайте сделаем это по одному.
союз союз и пересекаются
- Математическое понятие объединения, объединения множества A и множества B, выраженное как A ∪ B.
- Математическое понятие пересечения, пересечение множества A и множества B, выраженное как A ∩ B.
как показано на рисунке:
Теперь давайте сначала реализуем метод объединения // 并集
this.union = function (other) {
let union = new Set();
let values = this.values();
for (let i = 0; i < values.length; i++) {
union.add(values[i]);
}
values = other.values(); // 将values重新赋值为新的集合
for (let i = 0; i < values.length; i++) {
union.add(values[i]);
}
return union;
};
// 交集
this.intersect = function (other) {
let intersect = new Set();
let values = this.values();
for (let i = 0; i < values.length; i++) {
if (other.has(values[i])) { // 查看是否也存在于other中
intersect.add(values[i]); // 存在的话就像intersect中添加元素
}
}
return intersect;
};
Давайте взглянем на реализацию набора различий, а затем протестируем его вместе.
разница разница
- Математическая концепция разностного набора, разностный набор набора A и набора B, выраженный как AB
// 差集
this.difference = function (other) {
let difference = new Set();
let values = this.values();
for (let i = 0; i < values.length; i++) {
if (!other.has(values[i])) { // 将不存在于other集合中的添加到新的集合中
difference.add(values[i]);
}
}
return difference;
};
Установить полную реализацию
Вот, позвольте мне сначала опубликовать это для васПолный код реализации
function Set(arr = []) {
let items = {};
this.size = 0;
// has方法
this.has = function (val) {
return items.hasOwnProperty(val);
};
// add方法
this.add = function (val) {
// 如果没有存在items里面就可以直接写入
if (!this.has(val)) {
items[val] = val;
this.size++;
return true;
}
return false;
};
arr.forEach((val, i) => {
this.add(val);
});
// delete方法
this.delete = function (val) {
if (this.has(val)) {
delete items[val]; // 将items对象上的属性删掉
this.size--;
return true;
}
return false;
};
// clear方法
this.clear = function () {
items = {};
this.size = 0;
};
// keys方法
this.keys = function () {
return Object.keys(items);
};
// values方法
this.values = function () {
return Object.values(items);
}
// forEach方法
this.forEach = function (fn, context = this) {
for (let i = 0; i < this.size; i++) {
let item = Object.keys(items)[i];
fn.call(context, item, item, items);
}
}
// 并集
this.union = function (other) {
let union = new Set();
let values = this.values();
for (let i = 0; i < values.length; i++) {
union.add(values[i]);
}
values = other.values(); // 将values重新赋值为新的集合
for (let i = 0; i < values.length; i++) {
union.add(values[i]);
}
return union;
};
// 交集
this.intersect = function (other) {
let intersect = new Set();
let values = this.values();
for (let i = 0; i < values.length; i++) {
if (other.has(values[i])) {
intersect.add(values[i]);
}
}
return intersect;
};
// 差集
this.difference = function (other) {
let difference = new Set();
let values = this.values();
for (let i = 0; i < values.length; i++) {
if (!other.has(values[i])) {
difference.add(values[i]);
}
}
return difference;
};
// 子集
this.subset = function(other) {
if (this.size > other.size) {
return false;
} else {
let values = this.values();
for (let i = 0; i < values.length; i++) {
console.log(values[i])
console.log(other.values())
if (!other.has(values[i])) {
return false;
}
}
return true;
}
};
}
module.exports = Set;
Я много написал, давайте проверим вместе
const Set = require('./Set.js');
let set = new Set([2, 1, 3]);
console.log(set.keys()); // [ '1', '2', '3' ]
console.log(set.values()); // [ 1, 2, 3 ]
console.log(set.size); // 3
set.delete(1);
console.log(set.values()); // [ 2, 3 ]
set.clear();
console.log(set.size); // 0
// 并集
let a = [1, 2, 3];
let b = new Set([4, 3, 2]);
let union = new Set(a).union(b).values();
console.log(union); // [ 1, 2, 3, 4 ]
// 交集
let c = new Set([4, 3, 2]);
let intersect = new Set([1,2,3]).intersect(c).values();
console.log(intersect); // [ 2, 3 ]
// 差集
let d = new Set([4, 3, 2]);
let difference = new Set([1,2,3]).difference(d).values();
// [1,2,3]和[4,3,2]的差集是1
console.log(difference); // [ 1 ]
До сих пор мы использовали структуру данных set для реализации класса, аналогичного классу Set в ES6. Описанный выше метод использования в основном такой же. Если у вас есть время, вы можете коснуться его и посмотреть. Вы можете' Не пропустите его, когда будете проходить мимо.
Теперь, когда мы завершили реализацию Набора, хорошие вещи должны идти парами, и мы напишем Карту вместе за один раз.
Словарь
В структуре данных также есть структура, называемаяСловарьОн основан на реализации структуры карты классов ES6
Итак, в чем разница между набором и словарем:
- Общая основа: наборы и словари могут хранить уникальные значения
- Разница: коллекция хранит элементы в виде [значение, значение], а словарь хранит элементы в виде [ключ, значение].
Итак, на этот раз давайте поймем, что основная цель Map - хранить данные.По сравнению с Object, который обеспечивает только соответствие «строка-значение», Map обеспечивает соответствие «значение-значение». То есть, если вам нужна структура данных «пара ключ-значение», Map больше подходит, чем Object.
Давайте посмотрим на основное использование:
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false
Выше приведено основное использование Map, и есть более полезные методы, которые будут показаны позже с углубленной реализацией.
Свойства карты и методы
Атрибуты:
- размер: возвращает количество элементов, содержащихся в словаре
Метод работы:
- set(key, val): добавить новый элемент в словарь
- get(key): найти конкретное значение по значению ключа и вернуть
- has(key): возвращает true, если ключ существует в словаре, иначе false
- delete(key): удалить соответствующие данные из словаря по значению ключа
- clear(): удалить все элементы в этом словаре
Метод обхода:
- keys(): возвращает все имена ключей, содержащиеся в словаре, в виде массива.
- values(): возвращает все значения, содержащиеся в словаре, в виде массива
- forEach(): перебирает все элементы словаря.
Теперь, когда вы знаете, какие существуют свойства и методы, давайте отбросим сплетни и приступим к созданию словаря.
создать словарь
function Map() {
let items = {};
}
module.exports = Map; // 导出
После создания скелета словаря начните добавлять некоторые методы
имеет метод
В первую очередь, конечно, приходится на has, потому что он используется и в set, и в get, а идея реализации очень похожа на set, написанный ранее.
function Map() {
let items = {};
// has(key)方法
this.has = function(val) {
return items.hasOwnProperty(val);
};
}
После реализации метода has мы можем судить, содержится ли атрибут в словаре, и продолжить реализацию других методов.
установить и получить методы
// set(key, val)方法
// set相同key时,后面声明的会覆盖前面
// 如: new Map().set({}, 'a')
this.set = function(key, val) {
items[key] = val;
};
// get(key)方法
this.get = function(key) {
// 判断是否有key,如果有的话直接返回对应的值
// 如果读取一个未知的键,则返回undefined
return this.has(key) ? items[key] : undefined;
};
Записываются методы set и get, а затем следуют методы удаления и очистки, ничего лишнего, см.
удалить и очистить методы
// delete(key)方法
this.delete = function(key) {
if (this.has(key)) { // 如果有key值
delete items[key]; // 直接删掉items上对应的属性
this.size--; // 让size总数减1
return true;
}
return false;
};
// clear()方法
this.clear = function() {
items = {};
this.size = 0;
};
Атрибуты и методы работы были завершены отдельно выше, а окончательный метод обхода остается. Продолжайте писать. Настойчивость - это победа. Вам нелегко посмотреть чиновники. Давай! ! !
Метод обхода (ключи, значения, forEach)
// keys()方法
this.keys = function() {
return Object.keys(items);
};
// values()方法
this.values = function() {
return Object.values(items);
};
// forEach(fn, context)方法
this.forEach = function(fn, context = this) {
for (let i = 0; i < this.size; i++) {
let key = Object.keys(items)[i];
let value = Object.values(items)[i];
fn.call(context, value, key, items);
}
};
Теперь я, наконец, завершил реализацию класса Map и выложу полный код и тестовые примеры для изучения и анализа в свободное время.
Полная реализация карты
function Map() {
let items = {};
this.size = 0;
// 操作方法
// has方法
this.has = function(val) {
return items.hasOwnProperty(val);
};
// set(key, val)方法
this.set = function(key, val) {
items[key] = val;
this.size++;
};
// get(key)方法
this.get = function(key) {
return this.has(key) ? items[key] : undefined;
};
// delete(key)方法
this.delete = function(key) {
if (this.has(key)) {
delete items[key];
this.size--;
return true;
}
return false;
};
// clear()方法
this.clear = function() {
items = {};
this.size = 0;
};
// 遍历方法
// keys()方法
this.keys = function() {
return Object.keys(items);
};
// values()方法
this.values = function() {
return Object.values(items);
};
// forEach(fn, context)方法
this.forEach = function(fn, context = this) {
for (let i = 0; i < this.size; i++) {
let key = Object.keys(items)[i];
let value = Object.values(items)[i];
fn.call(context, value, key, items);
}
};
}
module.exports = Map;
Давайте посмотрим на следующие тестовые каштаны.
// map.js
// 使用Map类
const Map = require('./Map.js');
let m = new Map();
m.set('Jay', 'Jay的Chou');
m.set(true, '真的');
console.log(m.has('Chou')); // false
console.log(m.size); // 2
console.log(m.keys()); // [ 'Jay', 'true' ]
console.log(m.values()); // [ 'Jay的Chou', '真的' ]
console.log(m.get('jay')); // undefined
m.delete(true);
console.log(m.keys()); // [ 'Jay' ]
console.log(m.values()); // [ 'Jay的Chou' ]
Это не сводка
Финальная битва, неофициальное резюме
На основе двух структур данных коллекции и словаря реализованы структуры данных Set и Map, подобные ES6.
Но на самом деле доработка не идеальна, и есть еще некоторые методы, над которыми нужно подумать вместе.
Здесь я просто использую наборы и словари, чтобы дать вам фору.Я также надеюсь, что после прочтения вы сможете провести мозговой штурм и осознать это.
Хорошо, тогда спасибо за просмотр, спереди полно чепухи, это настоящая вещь, ха-ха