วิธีตรวจสอบว่าตารางมีองค์ประกอบใน Lua หรือไม่?


99

มีวิธีตรวจสอบว่าตารางมีค่าหรือไม่? ฉันมีฟังก์ชั่น (ไร้เดียงสา) เป็นของตัวเอง แต่ฉันสงสัยว่ามีบางอย่างที่ "เป็นทางการ" หรือไม่ หรือสิ่งที่มีประสิทธิภาพมากขึ้น ...

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

อย่างไรก็ตามเหตุผลหลักที่ฉันใช้ฟังก์ชันนี้คือการใช้ตารางเป็นชุดกล่าวคือไม่มีองค์ประกอบที่ซ้ำกัน มีอย่างอื่นที่ฉันสามารถใช้ได้หรือไม่?


3
สัญกรณ์ _ หมายถึงอะไร
Martin

24
มันเป็นเพียงแค่ "ขยะ" _ตัวแปรชื่อ pairs()คืนค่าkey, valueแต่ในตัวอย่างนี้ฉันต้องการเพียงค่าเท่านั้น เป็นแบบแผน (นำมาใช้ในหนังสือ "Programming in Lua" lua.org/pil/index.html ) เพื่อใช้_ตัวแปรนี้เพื่อจัดเก็บสิ่งที่ไม่ต้องการ
Wookai

ฉันเคยเห็นหลักการตั้งชื่อตัวแปร "ขยะ" ที่_ใช้ใน Python และ JavaScript ด้วย
iono

คำตอบ:


118

คุณสามารถใส่ค่าเป็นคีย์ของตารางได้ ตัวอย่างเช่น:

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

มีตัวอย่างที่มากขึ้นอย่างเต็มที่ที่โดดเด่นเป็นที่นี่


13
ผู้ใช้ที่ไม่ระบุชื่อเสนอการแก้ไขต่อไปนี้ให้กับโค้ดของคุณ: หากค่าในชุดที่มีคีย์ที่ระบุคือ FALSE ฟังก์ชัน setContains () จะส่งกลับเท็จแม้ว่าจะมีรายการในตารางที่มีคีย์ที่ระบุ บรรทัด "return set [key] ~ = nil" จะแก้ไขข้อผิดพลาดนั้น
oers

บางทีก็เช่นกันfunction keysOfSet(set) local ret={} for k,_ in pairs(set) do ret[#ret+1]=k end return ret end
Jesse Chisholm

24

ด้วยการเป็นตัวแทนของคุณฟังก์ชันของคุณจะมีประสิทธิภาพมากที่สุดเท่าที่จะทำได้ แน่นอนตามที่ผู้อื่นกล่าวไว้ (และตามที่ฝึกฝนในภาษาที่เก่ากว่า Lua) วิธีแก้ปัญหาที่แท้จริงของคุณคือเปลี่ยนการเป็นตัวแทน เมื่อคุณมีตารางและต้องการชุดคุณจะเปลี่ยนตารางเป็นชุดโดยใช้องค์ประกอบชุดเป็นคีย์และtrueเป็นค่า +1 ถึงอินเตอร์เจย์


3

ฉันรู้ว่านี่เป็นโพสต์เก่า แต่ฉันต้องการเพิ่มบางอย่างสำหรับคนรุ่นหลัง วิธีง่ายๆในการจัดการปัญหาที่คุณมีคือการสร้างตารางอื่นที่มีค่าเป็นกุญแจสำคัญ

กล่าวคือ. คุณมีตาราง 2 ตารางที่มีค่าเท่ากันตารางหนึ่งชี้ไปทางหนึ่งอีกตารางหนึ่งชี้ไปอีกทางหนึ่ง

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

จากนั้นคุณสามารถสอบถามตารางใหม่เพื่อดูว่ามีคีย์ "องค์ประกอบ" หรือไม่ ซึ่งจะช่วยป้องกันไม่ให้ต้องวนซ้ำทุกค่าของตารางอื่น ๆ

หากปรากฎว่าคุณไม่สามารถใช้ 'องค์ประกอบ' เป็นคีย์ได้จริงเนื่องจากไม่ใช่สตริงเช่นให้เพิ่มการตรวจสอบหรือtostringที่มันเป็นต้นจากนั้นใช้สิ่งนั้นเป็นคีย์

ทำไมคุณถึงต้องการทำเช่นนี้? หากตารางของคุณมีขนาดใหญ่มากระยะเวลาในการทำซ้ำในทุกองค์ประกอบจะมีความสำคัญทำให้คุณไม่สามารถทำบ่อย ค่าใช้จ่ายของหน่วยความจำเพิ่มเติมจะมีขนาดค่อนข้างเล็กเนื่องจากจะจัดเก็บพอยน์เตอร์ 2 ตัวไว้ที่วัตถุเดียวกันแทนที่จะเป็น 2 สำเนาของวัตถุเดียวกัน หากตารางของคุณมีขนาดเล็กมากก็จะมีความสำคัญน้อยกว่ามากซึ่งอาจทำให้การวนซ้ำเร็วกว่าการค้นหาแผนที่แบบอื่น

อย่างไรก็ตามข้อความของคำถามแสดงให้เห็นอย่างยิ่งว่าคุณมีรายการจำนวนมากที่ต้องจัดการ


คำอธิบายที่ดี แต่ไม่ได้เพิ่มอะไรในการสนทนา มันน่าจะเป็นความคิดที่ดีกว่าในการแก้ไขคำตอบของ interjay
bcdan

1
นอกจากนี้ ".key" ควรแทนที่ด้วย "[key]" ทุกที่ในรหัสนี้ (เช่นเดียวกับ "value")
Njol

2

ฉันคิดวิธีอื่นในการเปรียบเทียบค่าไม่ได้ แต่ถ้าคุณใช้องค์ประกอบของเซตเป็นคีย์คุณสามารถตั้งค่าเป็นค่าอื่นใดก็ได้ที่ไม่ใช่ศูนย์ จากนั้นคุณจะได้รับการค้นหาอย่างรวดเร็วโดยไม่ต้องค้นหาทั้งตาราง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.