루아 테이블에서 항목 수를 얻는 방법은 무엇입니까?


132

"Google에 알려주세요"라는 질문처럼 들리지만 어떻게 든 답을 찾을 수 없습니다. Lua #연산자는 정수 키가있는 항목 만 계산하므로 table.getn다음 과 같습니다.

tbl = {}
tbl["test"] = 47
tbl[1] = 48
print(#tbl, table.getn(tbl))   -- prints "1     1"

count = 0
for _ in pairs(tbl) do count = count + 1 end
print(count)            -- prints "2"

항목을 세지 않고 모든 항목 수를 얻으려면 어떻게합니까 ?


3
@lhf : 나는 본 모든 객체를 기억하는 시리얼 라이저를 작성했으며 다음에 볼 때 객체 대신 정수 참조를 방출합니다. 이 쓸 수있는 자연적인 방법은 같은 것입니다 dictionary[value] = #dictionary + 1, #의 수를 나타내는 모든 개체를. 무엇 나는 당신이 왜 궁금 것은 하지 않는 이 원하는 : 모두 제정신의 # (kaizer.se 의해 답변을 참조) 사용의 경우, 모든 객체의 수는 정확하게 이미 무엇 # 반환 같음; # 카운트를 모든 것을 엄격하게 개선하는 것 같습니다. 물론 나는 루아 초보자이며 요점을 놓칠 수 있습니다.
Roman Starkov

32
@lhf : 모든 합리적인 프로그래밍 언어가 간단한 기능을 가진 무언가를 왜해야하는지 물어 봄으로써 프로그래머의 능력에 의문을 갖는 것은 좋지 않습니다.
Timwi

5
@Timwi : Lua 언어 저자 중 한 명에게 Lua가 "합리적인"프로그래밍 언어 중 하나가 아니라고 말하는 것은 좋지 않습니다. ;-) BTW, 나는 그 정보도 필요하지 않았습니다.
Alexander Gladysh

5
단일 언어의 모든 기능을 사용한 적이 없다고 생각 합니다. 그것은 그들이 다른 사람들에게 유용하지 않다는 것을 의미하지는 않습니다 :)
Roman Starkov

7
@sylvanaar 제 생각에는 #운영자는 잘못 정의되어 있습니다. 이것은 매우 쉽게 고칠 수 있습니다. 첫째, #결정 론적이며, 둘째, 새로운 연산자 나 함수를 도입하여 과감한 수를 얻는 것입니다. 이야기의 끝 ... 왜 그렇게 고집 스러워야합니까? :)
Roman Starkov

답변:


129

당신은 이미 문제에 대한 해결책을 가지고 있습니다-유일한 방법은 전체 테이블을 반복하는 것입니다 pairs(..).

function tablelength(T)
  local count = 0
  for _ in pairs(T) do count = count + 1 end
  return count
end

또한 "#"연산자의 정의는 그보다 약간 더 복잡합니다. 이 표를 통해이를 설명해 드리겠습니다.

t = {1,2,3}
t[5] = 1
t[9] = 1

매뉴얼에 따라 임의의 3, 5, 9의 결과는 유효하다 #t. 그것을 사용하는 유일한 방법은 nil 값이없는 하나의 인접한 부분의 배열입니다.


42
나는 Lua에 대한 나의 경험에 대한 기억에 여전히 충격을 주었다 #.
로마 Starkov

5
아마도 결정론적일 것입니다. C 표준이 구현 정의 동작으로 남을 때와 정확히 동일합니다. 이와 같은 이유는 다른 구현자가 다른 구현 선택을 선택할 수 있기 때문입니다.
Nakedible

19
According to the manual, any of 3, 5 and 9 are valid results for #t. 매뉴얼에 따르면, 비 시퀀스에서 # 호출은 정의되지 않습니다 . 이는 모든 결과 (-1, 3, 3.14, 5, 9)가 유효 함을 의미합니다.
cubuspl42

6
유효한 결과와 관련하여 : u0b34a0f6ae는 Lua 5.1에 적합하고 cubuspl42는 Lua 5.2에 적합합니다. 두 경우 모두, 모든 것이 완전히 미쳤다.
Jeremy

9
비 시퀀스에서 #이 예외를 생성하지 않는다는 사실은 루아를 조금 더 기분 좋게 절단하는 것과 같은 것들 중 하나 일뿐입니다.
보트 코더

21

항목 수를 추적하도록 메타 테이블을 설정할 수 있습니다.이 정보가 자주 필요한 경우 반복보다 빠를 수 있습니다.


이 방법으로 항목 지우기를 처리하는 편리한 방법이 있습니까?
u0b34a0f6ae

슬프게도, 인덱스가 존재하지 않는 한 __newindex 함수는 nil 할당에서 실행되지 않는 것처럼 보이므로 특수 함수를 통해 항목 제거를 퍼널해야합니다.
ergosys

1
데이터를 별도의 테이블에 저장해야합니다 (예 : __index 및 __newindex의 업 밸류로 액세스 가능). 그런 다음 __index와 __newindex는 각 테이블 액세스에 대해 발생합니다. 그래도 성능이 수용 가능한지 확인해야합니다.
Alexander Gladysh

@Alexander : 아, 그리고 다음 걸림 점 : 테이블을 프록시 처리하면 쌍으로 정상적인 반복이 작동하지 않습니다. 루아 5.2에서 해결할 수 있습니다.
u0b34a0f6ae

5.2에는 __pairs 및 __ipairs 메타 메소드가있을 것입니다 ... 5.1에서 수행하려면 pairs () 함수를 자신의 것으로 바꿔야합니다. 그러나 아마도 너무 많을 것입니다. :-)
Alexander Gladysh

3

한 가지 방법이 있지만 실망 스러울 수 있습니다. 카운트를 저장하기 위해 추가 변수 (또는 테이블 필드 중 하나)를 사용하고 삽입 할 때마다 증가시킵니다.

count = 0
tbl = {}

tbl["test"] = 47
count = count + 1

tbl[1] = 48
count = count + 1

print(count)   -- prints "2"

다른 방법은 없습니다. # 연산자는 연속 키가있는 배열 형 테이블에서만 작동합니다.



프록시 테이블 / 메타 메소드 가이 시나리오를 아직 완전히 지원하지 않는다는 의견에서 인상을 얻었으므로 현재 사용 가능한 가장 좋은 방법으로 받아들입니다.
Roman Starkov

계산은 테이블의 유일한 방법이며, 테이블을 만들 때 행을 추가하는 것이 계산이 필요할 때마다 계산하는 기능보다 낫습니다. 카운트로 설정된 값으로 끝에 키를 추가 할 수 있습니다.
Henrik Erlandsson

2

테이블의 항목 수를 얻는 가장 쉬운 방법은 '#'입니다. #tableName은 번호가 매겨진 항목 수를 가져옵니다.

tbl={
    [1]
    [2]
    [3]
    [4]
    [5]
}
print(#tbl)--prints the highest number in the table: 5

안타깝게도 번호가 매겨지지 않으면 작동하지 않습니다.


2

펜 라이트 라이브러리를 사용할 수 있습니다 . size테이블의 실제 크기를 제공 하는 기능이 있습니다 .

Lua에서 프로그래밍하고 누락하는 동안 필요할 수있는 많은 기능을 구현했습니다.

다음은이를 사용하기위한 샘플입니다.

> tablex = require "pl.tablex"
> a = {}
> a[2] = 2
> a[3] = 3 
> a['blah'] = 24

> #a
0

> tablex.size(a)
3

1
local function CountedTable(x)
    assert(type(x) == 'table', 'bad parameter #1: must be table')

    local new_t = {}
    local mt = {}

    -- `all` will represent the number of both
    local all = 0
    for k, v in pairs(x) do
        all = all + 1
    end

    mt.__newindex = function(t, k, v)
        if v == nil then
            if rawget(x, k) ~= nil then
                all = all - 1
            end
        else
            if rawget(x, k) == nil then
                all = all + 1
            end
        end

        rawset(x, k, v)
    end

    mt.__index = function(t, k)
        if k == 'totalCount' then return all
        else return rawget(x, k) end
    end

    return setmetatable(new_t, mt)
end

local bar = CountedTable { x = 23, y = 43, z = 334, [true] = true }

assert(bar.totalCount == 4)
assert(bar.x == 23)
bar.x = nil
assert(bar.totalCount == 3)
bar.x = nil
assert(bar.totalCount == 3)
bar.x = 24
bar.x = 25
assert(bar.x == 25)
assert(bar.totalCount == 4)

1
답변을 게시 할 때는 질문에 직접 답변하는 최소한의 코드를 게시하고 코드가 질문에 어떻게 대답하는지 설명하는 것이 좋습니다. 여기를 참조하십시오 .
cst1992

__newindex새 키를 정의 할 때만 호출하므로 존재 키로 __newindex설정할 때 호출 할 기회가 없습니다 nil.
Frank AK

-1

테이블의 요소가 insert 메소드로 추가되면 getn이 올바르게 리턴됩니다. 그렇지 않으면 모든 요소를 ​​세어야합니다

mytable = {}
element1 = {version = 1.1}
element2 = {version = 1.2}
table.insert(mytable, element1)
table.insert(mytable, element2)
print(table.getn(mytable))

2를 올바르게 인쇄합니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.