Как называется эта хеш-подобная / древовидная конструкция? - PullRequest
6 голосов
/ 05 июня 2010

Я хочу создать класс "Config", который действует где-то между хешем и деревом. Это просто для хранения глобальных значений, которые могут иметь контекст.

Вот как я это использую:

Config.get("root.parent.child_b") #=> "value"

Вот как может выглядеть класс:

class Construct

  def get(path)
    # split path by "."
    # search tree for nodes
  end

  def set(key, value)
    # split path by "."
    # create tree node if necessary
    # set tree value
  end

  def tree
    {
      :root => {
        :parent => {
          :child_a => "value",
          :child_b => "another value"
        },
        :another_parent => {
          :something => {
            :nesting => "goes on and on"
          }
        }
      }
    }
  end

end

Есть ли название для такого рода вещей где-то между Hash и Tree (не по специальности «Информатика»)? В основном хеш-подобный интерфейс к дереву.

Что-то, что выводит как это:

t = TreeHash.new
t.set("root.parent.child_a", "value")
t.set("root.parent.child_b", "another value")

желаемый формат вывода:

t.get("root.parent.child_a") #=> "value"
t.get("root") #=> {"parent" => {"child_a" => "value", "child_b" => "another value"}}

вместо этого:

t.get("root") #=> nil

или это (из которого вы получаете значение, вызывая {}.value)

t.get("root") #=> {"parent" => {"child_a" => {}, "child_b" => {}}}

Ответы [ 5 ]

9 голосов
/ 05 июня 2010

Вы можете реализовать один в кратчайшие сроки:

class TreeHash < Hash
  attr_accessor :value

  def initialize
    block = Proc.new {|h,k| h[k] = TreeHash.new(&block)}
    super &block
  end

  def get(path)
    find_node(path).value
  end

  def set(path, value)
    find_node(path).value = value
  end

private

  def find_node(path)
    path.split('.').inject(self){|h,k| h[k]}
  end
end

Вы можете улучшить реализацию, установив ненужные Hash методы как частные, но они уже работают так, как вы этого хотели. Данные хранятся в хэше, поэтому вы можете легко преобразовать их в yaml.


EDIT:

Чтобы оправдать дальнейшие ожидания (и правильно конвертировать to_yaml по умолчанию), вы должны использовать модифицированную версию:

class TreeHash < Hash
  def initialize
    block = Proc.new {|h,k| h[k] = TreeHash.new(&block)}
    super &block
  end

  def get(path)
    path.split('.').inject(self){|h,k| h[k]}
  end

  def set(path, value)
    path = path.split('.')
    leaf = path.pop
    path.inject(self){|h,k| h[k]}[leaf] = value
  end
end

Эта версия является небольшим компромиссом, поскольку вы не можете хранить значения в неконечных узлах.

1 голос
/ 05 сентября 2011

Я думаю, что название структуры на самом деле является вложенным хешем , а код в вопросе является переизобретением словарей javascript. Поскольку словарь в JS (или Python или ...) может быть вложенным, каждое значение может быть другим словарем, который имеет свои собственные пары ключ / вал. В javascript это все, что является объектом.

И самое лучшее - это умение использовать JSON для точного его определения и передачи:

tree : {
  'root' : {
    'parent' : {
      'child_a' : "value",
      'child_b' : "another value"
    },
    'another_parent' : {
      'something' : {
        'nesting' : "goes on and on"
      }
    }
  }
};

В JS вы можете сделать tree.root.parent.child_a.

Этот ответ на другой вопрос предлагает использовать Hashie gem для преобразования объектов JSON в объекты Ruby.

0 голосов
/ 05 июня 2010

Э-э ... это, конечно, можно сделать, используя иерархическую хеш-таблицу, но зачем вам иерархия? Если вам нужно только точное соответствие get и put, почему вы не можете просто создать одну хеш-таблицу, в которой используется соглашение об именовании, разделенное точкой?

Это все, что нужно для реализации запрашиваемых вами функций, и это, очевидно, очень просто ...

0 голосов
/ 05 июня 2010

Зачем вообще использовать хеш-подобный интерфейс? Почему бы не использовать цепочку методов для навигации по вашему дереву? Например config.root.parent.child_b и использовать методы экземпляра и, если необходимо, method_missing() для их реализации?

0 голосов
/ 05 июня 2010

Я думаю, что это напоминает структуру данных TreeMap, аналогичную той, которая описана в Java, описанной здесь . Он делает то же самое (сопоставления ключ / значение), но поиск может отличаться, так как вы используете сами узлы в качестве ключей. Извлечение из описанного TreeMap абстрагируется от реализации, поскольку, когда вы передаете ключ, вы не знаете его точное местоположение в дереве.

Надеюсь, что это имеет смысл!

...