จะตรวจสอบได้อย่างไรว่าตัวแปรเป็นอาร์เรย์หรือไม่…หรือสิ่งที่คล้ายอาร์เรย์


90

ฉันต้องการใช้การforeachวนซ้ำกับตัวแปร แต่ตัวแปรนี้สามารถเป็นได้หลายประเภทNULLเช่น

ดังนั้นก่อนที่จะforeachทดสอบ:

if(is_array($var)){
  foreach($var as ...

แต่ฉันรู้ว่ามันสามารถเป็นคลาสที่ใช้Iteratorอินเทอร์เฟซได้ บางทีฉันอาจจะตาบอด แต่จะตรวจสอบได้อย่างไรว่าคลาสใช้อินเทอร์เฟซหรือไม่? มีบางอย่างเช่นis_aฟังก์ชันหรือinheritsตัวดำเนินการหรือไม่? ฉันพบว่าclass_implementsฉันสามารถใช้มันได้ แต่อาจมีบางอย่างที่ง่ายกว่านี้?

ประการที่สองที่สำคัญกว่าคือฉันคิดว่าฟังก์ชันนี้มีอยู่จะเพียงพอที่จะตรวจสอบว่าตัวแปรis_arrayหรือ "ใช้Iteratorอินเทอร์เฟซ" หรือไม่หรือฉันควรทดสอบอะไรเพิ่มเติม


2
ถ้า ($ var instance ของ ArrayIterator)
Alexey

ใช่ฉันแน่ใจมากว่ามันจะไม่ได้ผลที่ยังไม่ได้ดูคู่มือ ...
Voitcus

2
สามารถทำซ้ำวัตถุที่
Blackhole

คำตอบ:


80

หากคุณกำลังใช้foreachภายในฟังก์ชันและคุณกำลังคาดหวังอาร์เรย์หรืออ็อบเจกต์Traversableคุณสามารถพิมพ์คำใบ้ฟังก์ชันนั้นด้วย:

function myFunction(array $a)
function myFunction(Traversable)

หากคุณไม่ได้ใช้foreachภายในฟังก์ชันหรือคุณคาดหวังว่าทั้งสองอย่างคุณสามารถใช้โครงสร้างนี้เพื่อตรวจสอบว่าคุณสามารถวนซ้ำตัวแปรได้หรือไม่:

if (is_array($a) or ($a instanceof Traversable))

ขอบคุณ. ฉันหวังว่ามันจะเพียงพอและจะไม่มีโครงสร้างภาษาอื่นที่สามารถทำซ้ำได้
Voitcus

ฉันพบว่าis_arrayมีราคาแพง ค่าใช้จ่ายในการคำนวณดูเหมือนจะเพิ่มขึ้นตามขนาดของอาร์เรย์ (ซึ่งไม่สมเหตุสมผลเนื่องจากเพิ่งตรวจสอบว่าเป็นอาร์เรย์หรือไม่) แต่มันเกิดขึ้นกับฉันอย่างน่าตกใจในห้องสมุด ดูความคิดเห็นของฉันในคำถามที่เชื่อมโยง จะinstanceof Traversableทำงานกับอาร์เรย์หรือไม่ ฉันไม่ได้รับโอกาสทดสอบประสิทธิภาพของมัน
ADTC

@ADTC AFAIR อาร์เรย์เป็นตัวอย่างที่Traversableใช่
รองเท้า

1
@Shoe ฉันพยายามมันนี่ ด้วย$var = array(1,2,3);ผลลัพธ์คือ: is_array($var) = trueและ$var instanceof Traversable = false.
ADTC

@ADTC ใช่เพิ่งตรวจสอบ อาร์เรย์ไม่ได้ใช้งานIteratorจึงไม่สามารถใช้งานTraversableได้
รองเท้า

15

foreachสามารถจัดการอาร์เรย์และวัตถุ คุณสามารถตรวจสอบได้ด้วย:

$can_foreach = is_array($var) || is_object($var);
if ($can_foreach) {
    foreach ($var as ...
}

คุณไม่จำเป็นต้องตรวจสอบโดยเฉพาะอย่างTraversableที่คนอื่นบอกไว้ในคำตอบของพวกเขาเนื่องจากวัตถุทั้งหมดเช่นอาร์เรย์ทั้งหมดสามารถข้ามผ่านได้ใน PHP

เทคนิคเพิ่มเติม:

foreachทำงานร่วมกับ traversables ทุกชนิดเช่นกับอาร์เรย์กับวัตถุธรรมดา (ที่คุณสมบัติที่สามารถเข้าถึงได้ถูกส่งผ่าน) และTraversableวัตถุ (หรือมากกว่าวัตถุที่กำหนดget_iteratorตัวจัดการภายใน)

(ที่มา )

พูดง่ายๆในการเขียนโปรแกรม PHP ทั่วไปเมื่อใดก็ตามที่มีตัวแปร

  • อาร์เรย์
  • วัตถุ

และไม่ใช่

  • NULL
  • ทรัพยากร
  • สเกลาร์

คุณสามารถใช้foreachมัน


5

คุณสามารถตรวจสอบอินสแตนซ์Traversableด้วยฟังก์ชันง่ายๆ สิ่งนี้จะใช้ได้กับทั้งหมดนี้Iteratorเนื่องจากIterator extends Traversable

function canLoop($mixed) {
    return is_array($mixed) || $mixed instanceof Traversable ? true : false;
}

"? true: false" ส่วนซ้ำซ้อน อินสแตนซ์ของให้ค่าบูลอยู่แล้ว
Linas

2
<?php
$var = new ArrayIterator();

var_dump(is_array($var), ($var instanceof ArrayIterator));

ผลตอบแทนbool(false)หรือbool(true)


0

ฟังก์ชั่น

<?php

/**
 * Is Array?
 * @param mixed $x
 * @return bool
 */
function isArray($x) : bool {
  return !isAssociative($x);
}

/**
 * Is Associative Array?
 * @param mixed $x
 * @return bool
 */
function isAssociative($x) : bool {
  if (!is_array($array)) {
    return false;
  }
  $i = count($array);
  while ($i > 0) {
    if (!isset($array[--$i])) {
      return true;
    }
  }
  return false;
}

ตัวอย่าง

<?php

$arr = [ 'foo', 'bar' ];
$obj = [ 'foo' => 'bar' ];

var_dump(isAssociative($arr));
# bool(false)

var_dump(isAssociative($obj));
# bool(true)

var_dump(isArray($obj));
# bool(false)

var_dump(isArray($arr));
# bool(true)

0

เนื่องจาก PHP 7.1 มีประเภทหลอกiterableเพื่อจุดประสงค์นี้ Type-hinting iterableยอมรับอาร์เรย์ใด ๆ รวมทั้งการใช้งานTraversableอินเทอร์เฟซ PHP 7.1 is_iterable()ยังแนะนำฟังก์ชั่น สำหรับเวอร์ชันเก่าโปรดดูคำตอบอื่น ๆ ที่นี่สำหรับการดำเนินการบังคับใช้ประเภทที่เทียบเท่าโดยไม่ต้องใช้คุณสมบัติในตัวที่ใหม่กว่า

การเล่นที่ยุติธรรม: ดังที่ BlackHole ชี้ให้เห็นคำถามนี้ดูเหมือนจะซ้ำกันของวัตถุที่ทำซ้ำได้และคำใบ้ประเภทอาร์เรย์? และคำตอบของเขาหรือเธอมีรายละเอียดมากกว่าของฉัน

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