1 (изменено: Phoenixxx_Czar, 2022-01-25 14:56:12)

Тема: AHK: Классы Map и Set (полу аналог JavaScript)

Не хватало данного функционала и решил попробовать реализовать.

Зачем нужен Set? По сути это массив, в котором значения не могут повторяться, с помощью метода .has(value) можно узнать, есть ли данное значение в "списке".

+ Примеры использования Set

mySet := new Set()

mySet.add(1)
mySet.add(1)
mySet.add(1)
mySet.add(1)

mySet.values() ; [1]
mySet.size ; 1

mySet.add(5)

mySet.values() ; [1, 5]
mySet.size ; 2

mySet.has(5) ; true
mySet.has(3) ; false

mySet.delete(5)

mySet.values() ; [1]
mySet.size ; 1

mySet.add(53)
mySet.add(54)

mySet.values() ; [1, 53, 54]
mySet.size ; 3

mySet.clear()

mySet.values() ; []
mySet.size ; 0
mySet := new Set([1, 1, 3, 4, 5, 5, 123])
mySet.values() ; [1, 3, 4, 5, 123]

Так же можно добавлять в цепочке:

mySet := new Set()
mySet.add(1).add(1).add(3).add(4).add(5).add(5).add(123)
mySet.values() ; [1, 3, 4, 5, 123]

Зачем нужен Map? Ну.. По сути этот же объект, но с методом .has(key), который проверяет, находится ли key (ключ) в объекте. Ну и возможностью получить только ключ, только значения ну или массив с массивами [ключ, значение].

+ Примеры использования Map
myMap := new Map()

myMap.set("Ключ 1", "Значение 1")

myMap.size ; 1
myMap.get("Ключ 1") ; Значение 1
myMap.has("Ключ 1") ; true
myMap.entries() ; [["Ключ 1", "Значение 1"]]
myMap.values() ; ["Значение 1"]
myMap.keys() ; ["Ключ 1"]

myMap.delete("Ключ 1")
myMap.has("Ключ 1") ; false
myMap.entries() ; {}
myMap.values() ; []
myMap.keys() ; []

myMap.set("Ключ 1", "Значение 1")
myMap.set("Ключ 2", "Значение 2")
myMap.set("Ключ 3", "Значение 3")

; или:
; myMap.set("Ключ 1", "Значение 1").set("Ключ 2", "Значение 2").set("Ключ 3", "Значение 3")

myMap.size ; 3
myMap.entries() ; [["Ключ 1", "Значение 1"], ["Ключ 2", "Значение 2"], ["Ключ 3", "Значение 3"]]
myMap.values() ; ["Значение 1", "Значение 2", "Значение 3"]
myMap.keys() ; ["Ключ 1", "Ключ 2", "Ключ 3"]

myMap.clear()

myMap.entries() ; {}
myMap.values() ; []
myMap.keys() ; []

myMap := new Map([["Ключ 1", "Значение 1"]
				, ["Ключ 2", "Значение 2"]
				, ["Ключ 3", "Значение 3"]])

myMap.size ; 3
myMap.has("Ключ 1") ; true
myMap.entries() ; [["Ключ 1", "Значение 1"], ["Ключ 2", "Значение 2"], ["Ключ 3", "Значение 3"]]
myMap.values() ; ["Значение 1", "Значение 2", "Значение 3"]
myMap.keys() ; ["Ключ 1", "Ключ 2", "Ключ 3"]

+ Классы

/**
 * Методы:
 * - add(value)		Добавляет 'value' к Set объекту. Возвращает Set объект
 * - clear()		Удаляет все элементы из Set объекта
 * - delete(value)	Удаляет 'value' из Set объекта. Возвращает успешность удаления (true/false)
 * - has(value)		Проверяет, находится ли значение в Set объекте. Возвращает (true/false)
 * - values()		Возвращает все значение из Set объекта
 * Свойства:
 * - size			Возвращает количество значений в Set объекте
 */

class Set
{
	__new(arr := "")
	{
		this.data := []

		for index, value in arr
		{
			this.add(value)
		}
	}

	add(value)
	{
		if (!this.has(value))
		{
			this.data.push(value)
		}

		return this
	}

	clear()
	{
		this.data := []
	}

	delete(value)
	{
		if (index := this._indeOf(value))
		{
			this.data.delete(index)
		}

		return index ? true : false
	}

	has(value)
	{
		return this._indeOf(value) ? true : false
	}

	values()
	{
		return this.data.clone()
	}

	_indeOf(value)
	{
		for index, element in this.data
		{
			if (value == element)
			{
				return index
			}
		}

		return 0
	}

	size[]
	{
		get
		{
			return this.data.count()
		}

		set
		{
			return
		}
	}
}

/**
 * Методы:
 * - set(key, value)	Добавляет пару ключ-значение. Возвращает Map объект
 * - clear()			Удаляет все пары ключ-значеие из Map объекта
 * - delete(key)		Удаляет 'ключ' из Map объекта. Возвращает успешность удаления (true/false)
 * - has(key)			Проверяет, находится ли ключ в Map объекте. Возвращает (true/false)
 * - values()			Возвращает все значение из Map объекта
 * - keys()				Возвращает все ключи из Map объекта
 * - entries()			Возвращает массив с массивами из [key, value]
 * Свойства:
 * - size				Возвращает количество пар ключ-значение в Map объекте
 */

class Map
{
	__New(iterable := "")
	{
		this.data := {}

		for index, data in iterable
		{
			this.data[data[1]] := data[2]
		}
	}

	get(key)
	{
		return this.data[key]
	}

	set(key, value)
	{
		this.data[key] := value

		return this
	}

	has(key)
	{
		return this.data[key] ? true : false
	}

	delete(key)
	{
		if (isHas := this.has(key))
		{
			this.data.delete(key)
		}

		return isHas
	}

	clear()
	{
		this.data := {}
	}

	values()
	{
		arr := []

		for key, value in this.data
		{
			arr.push(value)
		}

		return arr
	}

	keys()
	{
		arr := []

		for key in this.data
		{
			arr.push(key)
		}

		return arr
	}

	entries()
	{
		arr := []

		for key, value in this.data
		{
			arr.push([key, value])
		}

		return arr
	}

	size[]
	{
		get
		{
			return this.data.count()
		}

		set
		{
			return
		}
	}
}

Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)

2

Re: AHK: Классы Map и Set (полу аналог JavaScript)

Возможно, в некоторых случаях подобные «удобняшки» будут полезны, но чаще всего можно обойтись простым трюком, используя ключ вместо значения:

obj := {}
obj[1] := 1
obj[1] := 2
obj[1] := 3

MsgBox, % obj.HasKey(1)
MsgBox, % obj.Count()
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3

Re: AHK: Классы Map и Set (полу аналог JavaScript)

Вообще преимущество Map и Set в JS еще в скорости, там происходит поиск во много раз быстрее, но увы, мы имеем AHK, думаю в v2 и будет работать нормально.

Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)

4

Re: AHK: Классы Map и Set (полу аналог JavaScript)

HasKey() тоже довольно быстро работает.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

5

Re: AHK: Классы Map и Set (полу аналог JavaScript)

Ну Map для меня всегда имел мало смысла, даже в JS, хотя он меня спасал, когда нужно было хранить оооочень много данных (больше 14.000.000), тогда он себя шикарно проявил.
А так, я делал в основном Set ибо польза на лицо.

Win10: LTSC (21H2); AHK: ANSI (v1.1.36.02)