Làm thế nào để kiểm tra xem một bảng có chứa một phần tử trong Lua hay không?


97

Có phương pháp nào để kiểm tra xem bảng có chứa giá trị không? Tôi có chức năng (ngây thơ) của riêng mình, nhưng tôi đã tự hỏi liệu có thứ gì đó "chính thức" cho điều đó không? Hoặc thứ gì đó hiệu quả hơn ...

function table.contains(table, element)
  for _, value in pairs(table) do
    if value == element then
      return true
    end
  end
  return false
end

Nhân tiện, lý do chính mà tôi sử dụng hàm này là sử dụng các bảng dưới dạng tập hợp, tức là không có phần tử trùng lặp. Có thứ gì khác tôi có thể sử dụng không?


3
ký hiệu _, nghĩa là gì?
Martin

24
Nó chỉ đơn giản là một biến "rác" được đặt tên _. pairs()trả về key, value, nhưng trong ví dụ này, tôi chỉ cần giá trị. Đó là một quy ước (được thông qua trong cuốn sách "Lập trình trong Lua" lua.org/pil/index.html ) để sử dụng _biến này để lưu trữ những thứ bạn không cần.
Wookai

Tôi đã thấy quy ước đặt tên cho các biến "rác" _được sử dụng trong Python và JavaScript.
iono

Câu trả lời:


115

Bạn có thể đặt các giá trị làm khóa của bảng. Ví dụ:

function addToSet(set, key)
    set[key] = true
end

function removeFromSet(set, key)
    set[key] = nil
end

function setContains(set, key)
    return set[key] ~= nil
end

Có một ví dụ đầy đủ tính năng hơn ở đây .


13
Một người dùng ẩn danh đã đề xuất bản sửa lỗi sau cho mã của bạn: Nếu giá trị trong tập hợp với khóa được chỉ định là FALSE thì hàm setContains () trả về giá trị false mặc dù có một mục trong bảng có khóa được chỉ định. dòng "return set [key] ~ = nil" sửa lỗi đó.
oers

Có lẽ cũngfunction keysOfSet(set) local ret={} for k,_ in pairs(set) do ret[#ret+1]=k end return ret end
Jesse Chisholm

24

Với sự đại diện của bạn, chức năng của bạn càng hiệu quả càng tốt. Tất nhiên, như những người khác đã lưu ý (và như được thực hành trong các ngôn ngữ cũ hơn Lua), giải pháp cho vấn đề thực sự của bạn là thay đổi cách biểu diễn. Khi bạn có bảng và bạn muốn tập hợp, bạn biến bảng thành tập hợp bằng cách sử dụng phần tử tập hợp làm khóa và truelàm giá trị. +1 để can thiệp.


2

Tôi không thể nghĩ ra cách khác để so sánh các giá trị, nhưng nếu bạn sử dụng phần tử của tập hợp làm khóa, bạn có thể đặt giá trị thành bất kỳ thứ gì khác ngoài nil. Sau đó, bạn nhận được các tra cứu nhanh chóng mà không cần phải tìm kiếm toàn bộ bảng.


2

Tôi biết đây là một bài viết cũ, nhưng tôi muốn thêm một cái gì đó cho hậu thế. Cách đơn giản để xử lý vấn đề mà bạn gặp phải là tạo một bảng khác, có giá trị thành khóa.

I E. bạn có 2 bảng có cùng giá trị, một bảng trỏ về một hướng, một bảng trỏ về hướng khác.

function addValue(key, value)
    if (value == nil) then
        removeKey(key)
        return
    end
    _primaryTable[key] = value
    _secodaryTable[value] = key
end

function removeKey(key)
    local value = _primaryTable[key]
    if (value == nil) then
        return
    end
    _primaryTable[key] = nil
    _secondaryTable[value] = nil
end

function getValue(key)
    return _primaryTable[key]
end

function containsValue(value)
    return _secondaryTable[value] ~= nil
end

Sau đó, bạn có thể truy vấn bảng mới để xem nó có 'phần tử' chính hay không. Điều này ngăn chặn sự cần thiết phải lặp qua mọi giá trị của bảng khác.

Nếu hóa ra là bạn thực sự không thể sử dụng 'phần tử' làm khóa, ví dụ: vì nó không phải là một chuỗi, thì hãy thêm tổng kiểm tra hoặc tostring trên đó chẳng hạn, rồi sử dụng nó làm khóa.

tại sao bạn muốn làm việc này? Nếu các bảng của bạn rất lớn, thì lượng thời gian để lặp lại mọi phần tử sẽ rất đáng kể, khiến bạn không thể làm việc đó thường xuyên. Chi phí bộ nhớ bổ sung sẽ tương đối nhỏ, vì nó sẽ lưu trữ 2 con trỏ đến cùng một đối tượng, thay vì 2 bản sao của cùng một đối tượng. Nếu các bảng của bạn rất nhỏ, thì nó sẽ ít quan trọng hơn nhiều, thậm chí có thể lặp lại nhanh hơn so với việc tra cứu bản đồ khác.

Tuy nhiên, từ ngữ của câu hỏi gợi ý rằng bạn có một số lượng lớn các mục cần giải quyết.


Một lời giải thích tốt, nhưng không thực sự thêm bất cứ điều gì vào cuộc thảo luận. Có lẽ nên chỉnh sửa câu trả lời của interjay.
bcdan

1
Ngoài ra, '.key' nên được thay thế bằng '[key]' ở khắp mọi nơi trong mã này (cùng với 'giá trị')
Njol
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.