LINUX.ORG.RU

История изменений

Исправление 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"