История изменений
Исправление theNamelessOne, (текущая версия) :
Это можно сделать в любом современном (и многих несовременных) языке, только сложность выше линейной сделать будет затруднительно. Вот Ruby:
Glob = Struct.new(:glob) do
def ===(other)
(other.is_a?(Glob) && other.glob == glob) || (other.is_a?(String) && File.fnmatch(glob, other))
end
end
def glob(glob)
glob.is_a?(Glob) ? glob : Glob.new(glob)
end
class FuzzyHash
Entry = Struct.new(:key, :value) do
def ===(other)
key === other
end
end
def initialize(hash = nil, &block)
@default = block
@entries = []
Hash(hash).each { |key, value| self[key] = value }
end
def []=(key, value)
Entry.new(key, value).tap { |entry| @entries << entry }
end
def [](key)
(@entries.find { |entry| entry === key } || default(key))&.value
end
def delete(key)
@entries.delete_if.with_object([]) do |entry, memo|
(entry === key).tap { |ret| memo << entry.value if ret }
end
end
def key?(key)
@entries.any? { |entry| entry === key }
end
private
def default(key)
return nil if @default.nil?
ret = @default.call(self, key)
ret.is_a?(FuzzyHash) ? ret : Entry.new(key, ret)
end
end
Пример в REPL:
pry(main)> hash = FuzzyHash.new /^(any|key|be|no|key)$/ => 'value', 'hello' => 'world', glob('foo*bar') => 'Dummy stuff', (1..Float::INFINITY) => 'Positive'
=> #<FuzzyHash:0x0000000231dc90
@default=nil,
@entries=
[#<struct FuzzyHash::Entry key=/^(any|key|be|no|key)$/, value="value">,
#<struct FuzzyHash::Entry key="hello", value="world">,
#<struct FuzzyHash::Entry key=#<struct Glob glob="foo*bar">, value="Dummy stuff">,
#<struct FuzzyHash::Entry key=1..Infinity, value="Positive">]>
pry(main)> hash['any']
=> "value"
pry(main)> hash['hello']
=> "world"
pry(main)> hash['fooizmus lebar']
=> "Dummy stuff"
pry(main)> hash[2.5]
=> "Positive"
Исправление theNamelessOne, :
Это можно сделать в любом современном (и многих несовременных) языке, только сложность выше линейной сделать будет затруднительно. Вот Ruby:
Glob = Struct.new(:glob) do
def ===(other)
(other.is_a?(Glob) && other.glob == glob) || (other.is_a?(String) && File.fnmatch(glob, other))
end
end
def glob(glob)
glob.is_a?(Glob) ? glob : Glob.new(glob)
end
class FuzzyHash
Entry = Struct.new(:key, :value) do
def ===(other)
key === other
end
end
def initialize(hash = nil, &block)
@default = block
@entries = []
Hash(hash).each { |key, value| self[key] = value }
end
def []=(key, value)
Entry.new(key, value).tap { |entry| @entries << entry }
end
def [](key)
(@entries.find { |entry| entry === key } || default(key))&.value
end
def delete(key)
@entries.delete_if.with_object([]) do |entry, memo|
(entry === key).tap { |ret| memo << entry.value if ret }
end
end
private
def default(key)
return nil if @default.nil?
ret = @default.call(self, key)
ret.is_a?(FuzzyHash) ? ret : Entry.new(key, ret)
end
end
Пример в REPL:
pry(main)> hash = FuzzyHash.new /^(any|key|be|no|key)$/ => 'value', 'hello' => 'world', glob('foo*bar') => 'Dummy stuff', (1..Float::INFINITY) => 'Positive'
=> #<FuzzyHash:0x0000000231dc90
@default=nil,
@entries=
[#<struct FuzzyHash::Entry key=/^(any|key|be|no|key)$/, value="value">,
#<struct FuzzyHash::Entry key="hello", value="world">,
#<struct FuzzyHash::Entry key=#<struct Glob glob="foo*bar">, value="Dummy stuff">,
#<struct FuzzyHash::Entry key=1..Infinity, value="Positive">]>
pry(main)> hash['any']
=> "value"
pry(main)> hash['hello']
=> "world"
pry(main)> hash['fooizmus lebar']
=> "Dummy stuff"
pry(main)> hash[2.5]
=> "Positive"
Исходная версия theNamelessOne, :
Это можно сделать в любом современном (и многих несовременных) языке, только сложность выше линейной сделать будет затруднительно. Вот Ruby:
Glob = Struct.new(:glob) do
def ===(other)
(other.is_a?(Glob) && other.glob == glob) || (other.is_a?(String) && File.fnmatch(glob, other))
end
end
def glob(glob)
glob.is_a?(Glob) ? glob : Glob.new(glob)
end
class FuzzyHash
Entry = Struct.new(:key, :value) do
def ===(other)
key === other
end
end
def initialize(hash = nil, &block)
@default = block
@entries = []
Hash(hash).each { |key, value| self[key] = value }
end
def []=(key, value)
Entry.new(key, value).tap { |entry| @entries << entry }
end
def [](key)
(@entries.find { |entry| entry === key } || default(key))&.value
end
def delete(key)
@entries.delete_if { |entry| entry === key }.map(&:value)
end
private
def default(key)
return nil if @default.nil?
ret = @default.call(self, key)
ret.is_a?(FuzzyHash) ? ret : Entry.new(key, ret)
end
end
Пример в REPL:
pry(main)> hash = FuzzyHash.new /^(any|key|be|no|key)$/ => 'value', 'hello' => 'world', glob('foo*bar') => 'Dummy stuff', (1..Float::INFINITY) => 'Positive'
=> #<FuzzyHash:0x0000000231dc90
@default=nil,
@entries=
[#<struct FuzzyHash::Entry key=/^(any|key|be|no|key)$/, value="value">,
#<struct FuzzyHash::Entry key="hello", value="world">,
#<struct FuzzyHash::Entry key=#<struct Glob glob="foo*bar">, value="Dummy stuff">,
#<struct FuzzyHash::Entry key=1..Infinity, value="Positive">]>
pry(main)> hash['any']
=> "value"
pry(main)> hash['hello']
=> "world"
pry(main)> hash['fooizmus lebar']
=> "Dummy stuff"
pry(main)> hash[2.5]
=> "Positive"