Ruby - ทดสอบอาร์เรย์


265

วิธีที่เหมาะสมในการ:

is_array("something") # => false         (or 1)

is_array(["something", "else"]) # => true  (or > 1)

หรือเพื่อให้ได้จำนวนสิ่งของในนั้น


7
คุณต้องการอาร์เรย์ที่แท้จริงหรือเพียงแค่บางสิ่งที่เหมือนอาร์เรย์
Kathy Van Stone

1
ไม่มีประเภทความปลอดภัยในทับทิม ไม่ต้องกังวลว่าตัวแปรของคุณจะเป็นอาร์เรย์หรือไม่ วิธีการควรจะถือว่าเป็นและไปข้างหน้าและนับจำนวนการโทร: my_array.count
user132447

โปรดอ่านคำตอบของ zgchurch และ DigitalRoss เพื่อหา Ruby ที่เป็นสำนวนมากขึ้น
DanT

คำตอบ:


516

kind_of()คุณอาจต้องการที่จะใช้

>> s = "something"
=> "something"
>> s.kind_of?(Array)
=> false
>> s = ["something", "else"]
=> ["something", "else"]
>> s.kind_of?(Array)
=> true

31
นอกจากนี้ยังมีและis_a? instance_of?ดูstackoverflow.com/questions/3893278/…
Nathan Long

2
การตรวจสอบประเภทสำหรับ Java ไปข้างหน้าและเพียงแค่โทรไปที่ตัวแปร เขียนการทดสอบหน่วยเพื่อให้แน่ใจว่าวิธีการทำงานตามที่คาดไว้
user132447

14
@ user132447 จริง ๆ แล้ว java เป็นประเภทที่ปลอดภัยดังนั้นคุณไม่จำเป็นต้องกังวลเกี่ยวกับการตรวจสอบประเภทใด ๆ
grinch

8
ฉันลงคะแนนตอนนี้เนื่องจากฉันไม่คิดว่านี่เป็นวิธีปฏิบัติที่ดีในภาษาอย่าง Ruby คำตอบโดย @zgchurch เป็นวิธีการที่ชัดเจนมากขึ้นสำหรับคำถาม ในกรณีเช่นนี้ฉันคิดว่ามันสมเหตุสมผลมากกว่าที่จะลองและคิดว่า OP หมายถึงอะไรมากกว่าที่จะให้ปืนลูกซองให้เขา ...
Per Lundberg

1
ทำไมคุณต้องการใช้kind_of?()โซลูชั่นอื่น ๆ คำอธิบายเกี่ยวกับประโยชน์ของคำตอบของคุณที่มีต่อผู้อื่นจะเป็นประโยชน์สำหรับผู้อ่านในอนาคต
AlbertEngelB

148

คุณแน่ใจหรือไม่ว่าต้องเป็นอาร์เรย์ คุณอาจสามารถใช้งานได้respond_to?(method)ดังนั้นโค้ดของคุณจะทำงานกับสิ่งที่คล้ายกันซึ่งไม่จำเป็นต้องใช้อาร์เรย์ หากคุณต้องการจริงๆarrayแล้วโพสต์ที่อธิบายArray#kind\_of?วิธีการที่ดีที่สุด

['hello'].respond_to?('each')

1
ในกรณีนี้ฉันแน่ใจว่ามันจะเป็นอาร์เรย์ แต่ยินดีที่ได้ทราบวิธีการนี้ด้วย +1
BuddyJoe

แนวคิดที่น่าสนใจฉันใช้ push / pop ในโครงสร้างข้อมูล มีอะไรนอกเหนือจากอาร์เรย์ที่ตอบสนองต่อวิธีการเหล่านั้นหรือไม่
ดึง

3
respond_to?(:to_ary)ถ้าคุณต้องการบางสิ่งบางอย่างมากขึ้นอาร์เรย์เช่นคุณอาจต้องการ
Andrew Grimm

21
โดยทั่วไปนี่เป็นวิธีปฏิบัติที่ดีสำหรับการพัฒนา OO ฉันอ่านที่บางคนพูดโดยทั่วไปว่า: อย่าจินตนาการว่าคุณกำลังเรียกวิธีการบนวัตถุของคุณ คุณกำลังส่งข้อความ หากวัตถุรู้วิธีตอบกลับข้อความของคุณคุณไม่สนใจว่าเป็นคลาสอะไรหรือมีวิธีการตั้งชื่อหรือไม่ว่าจะสร้างการตอบกลับแบบไดนามิกผ่าน method_missing หรือไม่ สิ่งสำคัญคือมันสามารถตอบสนองต่อข้อความของคุณ? สิ่งนี้ยอมให้มีการใช้ฟังก์ชั่นและการนำไปปฏิบัติได้ดีขึ้น คุณสามารถเปลี่ยนวัตถุที่คุณใช้ในภายหลังตราบใดที่มันยังตอบสนองได้อย่างถูกต้อง
Nathan Long

2
ปัญหาเดียวของเรื่องนี้คือฉันต้องการตรวจสอบว่ามีสิ่งที่ทำดัชนีได้หรือไม่ดังนั้นอาร์เรย์รายการที่ลิงก์ ฯลฯ จะเจ๋ง แต่ฉันไม่ต้องการที่เก็บค่าหลักเช่นแฮช
Colton Voege

58

แทนที่จะทดสอบArray,เพียงแค่แปลงสิ่งที่คุณได้รับในระดับเดียวArray,ดังนั้นโค้ดของคุณจำเป็นต้องจัดการกับเคสเดียว

t = [*something]     # or...
t = Array(something) # or...
def f *x
    ...
end

Ruby มีหลายวิธีในการประสาน API ซึ่งสามารถนำวัตถุหรือ Array ของวัตถุได้ดังนั้นลองเดาว่าทำไมคุณถึงอยากรู้ว่ามีอะไรบ้างที่เป็น Array ฉันมีคำแนะนำ

เครื่องหมายประกอบการมีจำนวนมากของเวทมนตร์ที่คุณสามารถมองขึ้นหรือคุณก็สามารถโทรArray(something)ซึ่งจะเพิ่มเสื้อคลุมอาร์เรย์ถ้าจำเป็น มันคล้ายกับ[*something]ในกรณีนี้

def f x
  p Array(x).inspect
  p [*x].inspect
end
f 1         # => "[1]"
f [1]       # => "[1]"
f [1,2]     # => "[1, 2]"

หรือคุณสามารถใช้เครื่องหมายในการประกาศพารามิเตอร์จากนั้น.flattenให้ตัวเรียงลำดับที่แตกต่างกัน (สำหรับเรื่องนั้นคุณสามารถโทร.flattenไปด้านบนด้วย)

def f *x
  p x.flatten.inspect
end         # => nil
f 1         # => "[1]"
f 1,2       # => "[1, 2]"
f [1]       # => "[1]"
f [1,2]     # => "[1, 2]"
f [1,2],3,4 # => "[1, 2, 3, 4]"

และขอบคุณgregschlomบางครั้งมันก็เร็วกว่าที่จะใช้Array(x)เพราะเมื่อมันมีอยู่แล้วArrayมันไม่จำเป็นต้องสร้างวัตถุใหม่


ดังนั้นคุณกำลังพูดว่าถ้ามันเป็นรายการเดียวมันทำให้มันเป็นอาร์เรย์ที่มีรายการเดียวในนั้น?
BuddyJoe

ใช่และถ้ามันเป็นอาร์เรย์อยู่แล้วมันจะเก็บมันไว้โดยไม่ต้องเพิ่ม wrapper แถวที่สอง
DigitalRoss

2
อย่าลืม: [*nil] => []. ดังนั้นคุณอาจจบลงด้วยอาร์เรย์ที่ว่างเปล่า
Christopher Oezbek

3
ใช้Array(foo)มีประสิทธิภาพมากขึ้นกว่า[*foo]
gregschlom

23

[1,2,3].is_a? Array ประเมินเป็นจริง


1
สิ่งนี้เพิ่มคำตอบที่ได้รับในเว็บไซต์เกือบเจ็ดปี .. ?
Martin Tournoij

6
@Carpetsmoker ไม่มีคำตอบสั้น ๆ ที่อ้างอิงis_a?ในกระทู้ทั้งหมดนี้ [1,2,3].is_a? Enumerableที่ใกล้เคียงที่สุดคือ ฉันยังคิดว่ามันมีค่าในขณะที่มีคำตอบนี้
dipole_moment

4
คุณรู้ .. คุณพูดถูกจริง ... ฉันสาบานได้ว่าฉันเห็นสิ่งนั้นอยู่ที่นั่นก่อนหน้านี้: - / มี upvote!
Martin Tournoij

16

ดูเหมือนคุณจะเป็นคนที่มีไอเท็มบางอย่าง Enumerableผมจึงอยากแนะนำให้เห็นว่ามันเป็น #countที่ยังรับประกันการดำรงอยู่ของ

ตัวอย่างเช่น,

[1,2,3].is_a? Enumerable
[1,2,3].count

ทราบว่าในขณะที่size, lengthและcountการทำงานทั้งหมดของอาร์เรย์countคือความหมายที่ถูกต้องที่นี่ - (ตัวอย่างเช่น'abc'.lengthและ'abc'.sizeการทำงานของทั้งสอง แต่'abc'.countไม่ทำงานเช่นนั้น)

ข้อควรระวัง: สตริง is_a? นับได้ดังนั้นบางทีนี่อาจไม่ใช่สิ่งที่คุณต้องการ ... ขึ้นอยู่กับแนวคิดของอาร์เรย์เช่นเดียวกับวัตถุ



6

พิจารณาใช้Array()ด้วย จากคู่มือสไตล์ชุมชน Ruby :

ใช้ Array () แทนที่จะเป็น Array check หรือ [* var] เมื่อจัดการกับตัวแปรที่คุณต้องการใช้เป็น Array แต่คุณไม่แน่ใจว่าเป็น Array

# bad
paths = [paths] unless paths.is_a? Array
paths.each { |path| do_something(path) }

# bad (always creates a new Array instance)
[*paths].each { |path| do_something(path) }

# good (and a bit more readable)
Array(paths).each { |path| do_something(path) }

สิ่งนี้จะสร้างผลลัพธ์ที่ไม่คาดคิดเมื่อผ่านแฮชเพราะto_aถูกเรียกในแต่ละอาร์กิวเมนต์ที่เพิ่มเข้าในอาร์เรย์ใหม่ดังนั้นให้Array({id: 100})ส่งคืน[[:id, 100]]
รนต์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.