LINUX.ORG.RU

Как в LUA реализовать струтуру данных - аналог perl-ового хеш хешей?


0

2

Почитал про таблицы - ну понятно вроде бы через них, но как конкретно работать (имеется ввиду адресация и получение списков) с ключами хешей разных уровней непонятно, как адресовать данные тоже непонятно, удалять хеши первого уровня и т.д.

или модуль какой необходим ...
просьба примеров побольше

★★★★

Не понимаю, в чём проблема. Что мешает использовать таблицу таблиц?

quantum-troll ★★★★★
()
Ответ на: комментарий от trashymichael

в чем разница-то?

второй вариант перловику ближе (:

Skolotovich ★★★
()
Ответ на: комментарий от quantum-troll
b = 'sdf'
c = 'zxc'
a = { b = { c = "yes"}}

b = 'sdddd'
c = 'zdddd'
a = { b = { c = "no"}}

b = 'sdddd'
c = 'zddde'
a = { b = { c = "no"}}

b = 'sddff'
c = 'zddff'
a = { b = { c = "yes"}}

b = 'sddff'
c = 'zeeff'
a = { b = { c = "yes"}}

b = 'sddff'
c = 'zdeff'
a = { b = { c = "yes"}}


Как распечатать элементы хэша первого уровня, второго чтобы была видно вложенность?
Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от Vlad-76
b = 'sdf'
c = 'zxc'
a = { [b] = { [c] = "yes"}}

Я вынужден тебя починить: иначе b — имя, а не выражение.

Как распечатать элементы хэша первого уровня, второго чтобы была видно вложенность?

Если ты имеешь в виду нечто вроде { ... = ...}, то lua из коробки не умеет — гугли lua pretty print, библиотек для подобного полно.

quantum-troll ★★★★★
()
Ответ на: комментарий от quantum-troll

Разницу пока

a = { [b] = { [c] = "yes"}} 
вместо
a = { b = { c = "yes"}}
не улавливаю

«Если ты имеешь в виду нечто вроде { ... = ...}, то lua из коробки не умеет — гугли lua pretty print, библиотек для подобного полно.» Красота размещения в STDOUT не важна.

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

типа вот так - но это не работает

local c
for k,v in ipairs(a) do
    for m in ipairs(a.k) do
        print (k .. " => " .. v)
        c = c + 1
    end
    print ("Всего элементов для: ", k ," ", c)
end

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от Vlad-76

не улавливаю

в случай с a = { b = { c = «yes»}}, b и с являются именами. т.е. a[«b»][«c»] эквивалентно a.b.c

а вариант

a = { [b] = { [c] = "yes"}}
будет резолвить переменные b и с, т.е.
> b = 'sdf'
> c = 'zxc'
> a = { [b] = { [c] = "yes"}}
> = a.sdf.zxc
yes
> = a["sdf"]["zxc"]
yes

Skolotovich ★★★
()
Последнее исправление: Skolotovich (всего исправлений: 1)
Ответ на: комментарий от Skolotovich

в случай с a = { b = { c = «yes»}}, b и с являются именами. т.е. a[«b»][«c»] эквивалентно a.b.c

ну т.е. b и c это были значения а а в скобках [b] [c] это переменные?

приблизительно как то так себе и представлял этот синтаксис ...
остается еще один вопрос :) как циклично вывести индексы и значения?

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от Vlad-76

http://lua-users.org/wiki/TableSerialization http://www.lua.ru/doc/5.1.html

local c = 0
for k,v in pairs(a) do
    for m in pairs(a[k]) do
        print (k, " => ", v[m])
        c = c + 1
    end
    print ("Всего элементов для: ", k ," ", c)
end
И снова: точка не приемлет после себя ничего кроме имени, для переменных, вызовов функций и прочих выражений используй скобки.

---
Если b=«foo», то {=...} аналогичен «foo» => ..., а {b=... } — «b» => ...

quantum-troll ★★★★★
()
Ответ на: комментарий от Skolotovich

ругается

/usr/local/bin/luajit-2.0.0: ./hoh2.lua:44: stack overflow
stack traceback:
        ./hoh2.lua:44: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ...
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:46: in function 'printtbl'
        ./hoh2.lua:53: in main chunk
        [C]: at 0x0804b4f0

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от quantum-troll
b = 's1'
c = 'zxc'
a = { [b] = { [c] = "yes"}}

b = 's2'
c = 'zdddd'
a = { [b] = { [c] = "no"}}

b = 's2'
c = 'zddde'

a = { [b] = { [c] = "no"}}

b = 's3'
c = 'z1'
a = { [b] = { [c] = "yes"}}

b = 's3'
c = 'z2'
a = { [b] = { [c] = "no"}}

b = 's3'
c = 'z3'
a = { [b] = { [c] = "yes"}}

print (a["s3"]["z3"])
print (a["s3"]["z2"])
print (a["s3"]["z1"])

function printtbl(tbl)
    local write = io.write
    for k,v in pairs(tbl) do
        if type(v) == "table" then
            write(" {")
            printtbl(v)
             write("} ")
        else
            write(k, "=>", v, " ")
        end
    end
end

printtbl(a) ; print()

выдает

# ./hoh4.lua
yes
nil
nil
 {z3=>yes }

Похоже так набивать хеш хешами неправильно, почему то в таблице всего лишь один элемент

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от Vlad-76

Наверное, потому, что ты делаешь присваивание вместо добавления?
Ты или a[«foo»] = {[«bar»] = «baz»} делай, или table.insert, если ты используешь таблицу как список, а не как хеш-таблицу.

quantum-troll ★★★★★
()
Ответ на: комментарий от Vlad-76

все правильно оно отдает, поросто имя ключа в случае таблицы не печатает

function printtbl(tbl)
    local write = io.write
    for k,v in pairs(tbl) do
        if type(v) == "table" then
            write(k, " => {")
            printtbl(v)
            write("} ")
        else
            write(k, " => ", v, " ")
        end
    end
end

и вообще уже мог бы сам это доделать

Skolotovich ★★★
()
Ответ на: комментарий от anonymous
Также по аналогии:

Lua:  x = "some key"
Perl: $x = "some key"

Lua:  t.x     равнозначно t["x"]
Perl: $t->{x} равнозначно $t->{"x"}

Lua:  t[x]
Perl: $t->{$x}
anonymous
()

Вот простой принтер:

cars = {
    {
        name = "Toyota",
        year = 2005,
    },
    {
        ["name"] = "Nissan",
        ["year"] = 2001,
        info = {
            nOwners = 2,
        },
    },
}

function showkv(k, v)
    if type(v) == "table" then
        v = string.format("{\n%s,\n}", show(v))
    elseif type(v) == "number" then
        v = string.format("%d", v)
    else
        v = string.format("%q", v)
    end
    if type(k) == "number" and math.floor(k) == k then
        k = string.format("%d", k)
    else
        k = string.format("%q", k)
    end
    return string.format("[%s] => %s", k, v)
end

function show(t)
    local lines = { }
    for k,v in pairs(t) do
        lines[#lines+1] = showkv(k, v)
    end
    return table.concat(lines, ",\n")
end

print(show(cars))
print(cars[1].name)
print(cars[2].name, cars[2].info.nOwners)
print(cars[2]["name"], cars[2]["info"]["nOwners"])

anonymous
()
Ответ на: комментарий от Skolotovich

к этому моменту выяснилась другая проблема :) - хеш был не набит
а алгоритм понятен

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от Vlad-76

это не работает

a = {}
a["foo"] = {["bar"] = "baz"}

вове дели два яблока... переменные кто инициализировать будет?

Skolotovich ★★★
()
Последнее исправление: Skolotovich (всего исправлений: 2)
Ответ на: комментарий от anonymous

в данном случае у массива cars предопределены значения индексов хешей, в моем случае из файла читаются пары IP адресов - которые случайны...

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от Vlad-76

Пока из обсуждения не понятно решилась проблема или нет. Если из файла грузится таблица через loadfile, то ее можно обойти через for k,v in pairs(t). Если ты сам кладешь данные в таблицу, то непонятно в чем проблема, синтакс непривычный просто?

anonymous
()
Ответ на: комментарий от Vlad-76

Перечитал тред. В перле ты обычно бежишь по keys %h и в теле цикла получаешь $h{$_}. В Луа так не делают, и.к. Нет прямого способа получить все ключи. Вместо этого используют цикл for k,v in pairs(h). Pairs возвращает итератор next, который возвращает по ключу следующий ключ, т.о. обходятся все пары. Next это обычная функция — next(t, nil) вернет первый ключ.

anonymous
()
Ответ на: комментарий от anonymous

Сейчас проблема - не получается добавить элемент.
этот код создает несколько элементов

b = 's2'
c = 'z1'
d = 'z2'
a[b] = { [c] = "s2z1" , [d] = "s2z2" }

результат s2 => {z1 => s2z1 z2 => s2z2} (последний элемент)
но у меня новые элементы появляются случайно
Этот код перезатирает
b = 's2'
c = 'z1'
a[b] = { [c] = "s2z1" }

b = 's2'
c = 'z2'
a[b] = { [c] = "s2z2"}

результат s2 => {z2 => s2z2}

А нужно добавлять очередной элемент к уже существующим
чтобы результат при появлении нового элемента был таким


результат s2 => {z1 => s2z1}
результат s2 => {z1 => s2z1 z2 => s2z2}
результат s2 => {z1 => s2z1 z2 => s2z2 z3 => s2z3 }
результат s2 => {z1 => s2z1 z2 => s2z2 z3 => s2z3 z4 => s2z4 }
и т.д.
вместо s2 и z1 будут значения IP адресов

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от Vlad-76
a = { }
a[b] = { } -- создаем подтаблицу
c = ...
a[b][c] = x -- пишем в нее
c = ...
a[b][c] = y -- пишем в нее

-- А ты затираешь каждый раз a[b] новой таблицей.
anonymous
()
Ответ на: комментарий от Vlad-76

Ты бы сразу написал, что хранишь реляцию айпишников один ко многим, проще было бы понимать.

t = { }
function addrelation(ipa, ipb)
  t[ipa] = t[ipa] or { }
  t[ipa][ipb] = true
end

...

addrelation(x, y)
addrelation(x, z)

if t[x][y] then
  -- x relates with y
end
anonymous
()
Ответ на: комментарий от anonymous

ура,заработало, СПАСИБО... и спасибо всем :)!
PS
a[b] = { } — создаем подтаблицу - вот это был ключевой момент

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от anonymous
-- remove relations for ipa
t[ipa] = nil


for ipa,subt in pairs(t) do
  for ipb in pairs(subt) do
    print(ipa, "relates to", ipb)
  end
end
anonymous
()
Ответ на: комментарий от Vlad-76

но не позволило бы дойти до того - что в луа необходимо все очевидно определять

Vlad-76 ★★★★
() автор топика
Ответ на: комментарий от Vlad-76

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

Ты только не каждый раз присваивай, если там уже есть подтаблица, не надо = { }.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.