Lua 테이블이 비어 있는지 (항목을 포함하지 않음) 확인하는 가장 효율적인 방법은 무엇입니까?


120

테이블이 비어 있는지 확인하는 가장 효율적인 방법은 무엇입니까 (즉, 현재 배열 스타일 값도 dict 스타일 값도 포함하지 않음)?

현재 사용하고 있습니다 next().

if not next(myTable) then
    -- Table is empty
end

더 효율적인 방법이 있습니까?

참고 : #연산자는 테이블의 배열 스타일 값에서만 작동하므로 여기에서 충분하지 않습니다. 따라서 둘 다 0을 반환하기 때문에 #{test=2}구분할 수 없습니다. #{}또한 테이블 변수가 있는지 확인하는 nil것으로는 충분하지 않습니다. nil 값이 아니라 항목이 0 인 테이블 (예 :) {}.

답변:


151

코드는 효율적이지만 잘못되었습니다. (고려하십시오 {[false]=0}.) 올바른 코드는

if next(myTable) == nil then
   -- myTable is empty
end

최대 효율성 next을 위해 로컬 변수 에 바인딩하고 싶을 것입니다 .

...
local next = next 
...
... if next(...) ...

1
기술적 정확성에 대한 좋은 점; 특정 경우에 원래 코드를 사용하고 있었지만 false예상되는 키가 아니므로 if not잘 작동했지만 nil좋은 습관처럼 앞으로 대신 비교하는 습관을 만들 것입니다 . 그리고 네, 속도를 위해 공통 유틸리티 함수를 로컬 변수에 바인딩했습니다. 그래도 입력 해 주셔서 감사합니다.
Amber

1
코드로 작동 할 때 나는 하드 그름에 동의 찾을 예정
RD Alkire

4
수행함으로써 속도를 얻는 이유는 무엇 local next입니까?
Moberg

2
@Moberg LUA가 네임 스페이스를 처리하는 방법 때문입니다. 아주 멍청한 버전은 먼저 로컬 테이블을 올라갈 것이므로 local next현재 블록에 a가 있으면이를 사용하고 다음 블록으로 올라간 다음 반복합니다. 지역을 벗어나면 글로벌 네임 스페이스를 사용합니다. 이것은 그것의 멍청한 버전이지만 결국 프로그램 속도와 관련하여 분명히 차이를 의미합니다.
ATaco 2016

@Moberg는 lua 5.2 및 5.3의 맥락에서 덜 멍청한 버전으로 비 로컬은 upval 또는 _ENV 조회입니다. upval은 추가 간접 레이어를 거쳐야하는 반면 _ENV 조회는 테이블 조회입니다. 반면 로컬 VM 내의 레지스터이다
이의 Rumed

1

한 가지 가능성은 메타 테이블 "newindex"키를 사용하여 요소 수를 계산하는 것입니다. 아닌 것을 할당 할 때는 nil카운터를 늘리고 (카운터는 메타 테이블에도있을 수 있음) 할당 할 때는 nil카운터를 줄입니다.

빈 테이블에 대한 테스트는 카운터를 0으로 테스트하는 것입니다.

다음은 메타 테이블 문서에 대한 포인터입니다.

나는 당신의 솔루션을 좋아하고 솔직히 내 솔루션이 전반적으로 더 빠르다고 생각할 수 없습니다.


5
원래 질문은 단순히 "배열"항목을 세는 것이 아닙니다.
lhf 2009-08-10

3
0x6의 제안은 배열 스타일 항목에만 국한되지 않습니다 (newindex는 숫자 및 비 숫자 인덱스 모두에서 작동 함). 그러나 nil키가 이미 테이블에 있으면 __newindex가 트리거되지 않기 때문에 주요 문제 는 할당 된 시기를 감지하는 것 입니다.
Amber

3
이 트릭이 작동하려면 메타 테이블이 __index및을 모두 구현해야 __newindex하며 실제 데이터를 새도우 테이블에 저장하고 실제 테이블을 비워 두어야 __index합니다. 큰 소리로 생각하면 모든 단일 조회의 증가 된 비용은 그만한 가치가 없다고 생각합니다.
RBerteig

0

이것은 아마도 당신이 원했던 것입니다.

function table.empty (self)
    for _, _ in pairs(self) do
        return false
    end
    return true
end

a = { }
print(table.empty(a))
a["hi"] = 2
print(table.empty(a))
a["hi"] = nil
print(table.empty(a))

산출:

true
false
true

11
next()반복하는 것보다 더 효율적이고 간결 pairs()합니다.
Amber

8
사실, 루프 오버 pairs() 본질적으로 next()기술을 사용하는 것이지만 오버 헤드가 더 많습니다.
dubiousjim

7
또한 표준 table라이브러리에 쓰는 것은 권장되지 않습니다.
Ti Strga 2014

-1

오버로드 된 경우 __eq의 평가를 피하는 것이 좋습니다.

if rawequal(next(myTable), nil) then
   -- myTable is empty
end

또는

if type(next(myTable)) == "nil" then
   -- myTable is empty
end

1
나는이 답변이 왜 투표가 거부되었는지 이해하려고 노력하는 Lua noob입니다. 나는 Lua에서 "두 객체가 다른 메타 메서드를 가지고 있다면, 메타 메소드를 호출하지 않고도 동등 연산이 거짓이되기 때문"이라고 생각합니다. (이 인용문은 Lua.org의 Programming in Lua에서이 페이지 하단에 있습니다.) nil에 대한 __eq 오버로딩을 피할 필요가 없습니까?
SansWit

-1

뱀을 시도하고 나를 위해 일하십시오

serpent = require 'serpent'

function vtext(value)
  return serpent.block(value, {comment=false})
end

myTable = {}

if type(myTable) == 'table' and vtext(myTable) == '{}' then
   -- myTable is empty
end

-2

이건 어때요 ?

if endmyTable[1] == nil then
  -- myTable is empty
end

1
인덱스와 같은 문자열 인 테이블에서는 작동하지 않습니다
SamHoque

-3

나는 이것이 오래되었다는 것을 알고 있으며 어떻게 든 당신을 오해 할 수 있지만 테이블이 비어 있기를 원합니다. 즉, 그것이 있는지 확인하고 실제로 비워두기를 원하지 않거나 필요로하지 않는 한, 내가 착각하지 않는 한 간단히 다시 생성하여 지울 수 있습니다. 이것은 아래 구문으로 수행 할 수 있습니다.

yourtablename = {} -- this seems to work for me when I need to clear a table.

4
그것은 질문이 아닙니다.
Yu Hao

-6

을 사용해보십시오 #. 테이블에있는 모든 인스턴스를 반환합니다. 테이블에 인스턴스가 없으면 다음을 반환합니다.0

if #myTable==0 then
print('There is no instance in this table')
end

1
질문자는 #여기에서 충분하지 않을 것이라고 말하고 그 이유를 설명합니다. 왜 이것이 그 이유를 우회하는지 설명해 주시겠습니까?
ameed jan

내가 아는 유일한 방법은 # 사용되도록 음 ... 나도 몰라이에 새로운 오전 할
arthurgps2
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.