草庐IT

PHP 行为和数组指针

coder 2024-04-12 原文

我在阅读 PHP 手册(特别是 each() 函数)时遇到了以下警告:

Caution
Because assigning an array to another variable resets the original array's pointer, our example above would cause an endless loop had we assigned $fruit to another variable inside the loop.

还有一个例子:

<?php
$fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry');

reset($fruit);
while (list($key, $val) = each($fruit)) {
    echo "$key => $val\n";
}
?>

好的。这说得通。但我决定做一个简单的测试:

<?php
    $fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry');

    foreach ($fruit as $key => $name) {
        printf("[%s] => [%s]\n", $key, $name);
    }

    $fruit2 = $fruit;
    echo current($fruit);
?>

结果符合预期:指针已重置。我的问题是指针是否仅在数组结束后才重置?

例如:

<?php
    $fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry');

    foreach ($fruit as $key => $name) {
        printf("[%s] => [%s]\n", $key, $name);
    }

    reset($fruit);
    next($fruit)."\n";
    $fruit2 = $fruit;
    echo current($fruit);
?>

指针保留在第二个数组元素 ('b' => 'banana') 中。 这种行为是语言的特征?

谢谢你,抱歉英语不好。

最佳答案

This behavior is characteristic of language?

PHP 数组中“指针”的含义与“指针”的一般含义(在 C/C++ 或其他允许程序员直接访问内存的语言中)不同。

PHP 中没有指针。 array数据类型在其包含的值列表内部保留一个游标。它被称为数组的内部指针,它被函数修改 reset() , next() , prev() , end() , each() 也许还有其他人。它可用于像这样遍历数组:

$array = array(1, 2, 3);
while (list($key, $val) = each($array)) {
    echo($key.' => '.$val."\n");
}

没有可靠的方法使用 next() 迭代数组或 prev() 因为他们返回 FALSE当没有更多元素要迭代但它们也返回 FALSE 时当值 FALSE作为一个元素存储在数组中。

如果您只需要分析数组开头(或结尾)的几个项目,它们可能很有用。 F.e.假设我们有一个函数返回的整数数组,我们需要获取第一个不为零的值。

但是使用 foreach() 可以更轻松地实现这个目标:

$array = array(0, 0, 0, 2, 0, 1, 0, 3);
foreach ($array as $val) {
    if ($val != 0) {
        break;
    }
}
echo($val);           // prints "2"

array_shift() :

$array = array(0, 0, 0, 2, 0, 1, 0, 3);
do {
    $val = array_shift($array);
    if ($val != 0) {
        break;
    }
} while(count($array));
echo($val);           // prints "2"

The result is expected: the pointer has been reset. My question is if the pointer is reset only after the end of the array?

foreach() 的文档是错的。也许它在 PHP 3 和 PHP 4 上是正确的,但我认为自从引入 iterators 以来在 PHP 5 中 foreach() 的行为改变(变得更好)。

它说:

When foreach first starts executing, the internal array pointer is automatically reset to the first element of the array. This means that you do not need to call reset() before a foreach loop.

As foreach relies on the internal array pointer, changing it within the loop may lead to unexpected behavior.

一个简单的测试与这个陈述相矛盾:

$array = array(1, 3, 5, 7, 9);

foreach ($array as $val1) {
    foreach ($array as $val2) {
        echo('$val1='.$val1.'; $val2='.$val2.'; ');
    }
    echo("\n");
}

它工作没有问题。如果 foreach() 它不应该工作正在使用内部数组指针。它可能会创建指针的副本。

你也可以尝试使用current() , next() , prev()reset()foreach()里面你会得到令人惊讶的,有时甚至是不一致的结果。

你最好使用foreach()遍历数组并且不以任何方式依赖内部指针。

函数reset()end()但是,当您需要获取数组的第一个和最后一个元素而不用担心键时,它们非常方便。

关于PHP 行为和数组指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30446546/

有关PHP 行为和数组指针的更多相关文章

  1. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  2. ruby - Ruby gsub 替换中的行为不一致? - 2

    两个gsub产生不同的结果。谁能解释一下为什么?代码也可在https://gist.github.com/franklsf95/6c0f8938f28706b5644d获得.ver=9999str="\tCFBundleDevelopmentRegion\n\ten\n\tCFBundleVersion\n\t0.1.190\n\tAppID\n\t000000000000000"putsstr.gsub/(CFBundleVersion\n\t.*\.).*()/,"#{$1}#{ver}#{$2}"puts'--------'putsstr.gsub/(CFBundleVersio

  3. ruby-on-rails - Ruby 中意外的大小写行为 - 2

    我在一段非常简单的代码(如我所想)中得到了一个错误的值:org=4caseorgwhenorg=4val='H'endputsval=>nil请不要生气,我希望我错过了一些非常明显的东西,但我真的想不通。谢谢。 最佳答案 这是典型的Ruby错误。case有两种被调用的方法,一种是你传递一个东西作为分支的基础,另一种是你不传递的东西。如果您确实在case中指定了一个表达式语句然后评估所有其他条件并与===进行比较.在这种情况下org评估为false和org===false显然不是真的。所有其他情况也是如此,它们要么是真的,要么是假的。

  4. ruby - 使对象的行为类似于 ruby​​ 中并行分配的数组 - 2

    假设您在Ruby中执行此操作:ar=[1,2]x,y=ar然后,x==1和y==2。是否有一种方法可以在我自己的类中定义,从而产生相同的效果?例如rb=AllYourCode.newx,y=rb到目前为止,对于这样的赋值,我所能做的就是使x==rb和y=nil。Python有这样一个特性:>>>classFoo:...def__iter__(self):...returniter([1,2])...>>>x,y=Foo()>>>x1>>>y2 最佳答案 是的。定义#to_ary。这将使您的对象被视为要分配的数组。irb>o=Obje

  5. ruby - 鸭子输入字符串、符号和数组的优雅方式? - 2

    这是针对我无法破坏的现有公共(public)API,但我确实希望对其进行扩展。目前,该方法采用字符串或符号或任何其他在作为第一个参数传递给send时有意义的内容我想添加发送字符串、符号等列表的功能。我可以只使用is_a吗?数组,但还有其他发送列表的方法,这不是很像ruby​​。我将调用列表中的map,所以第一个倾向是使用respond_to?:map。但是字符串也会响应:map,所以这行不通。 最佳答案 如何将它们全部视为数组?String的行为与仅包含String的Array相同:deffoo(obj,arg)[*arg].eac

  6. ruby - 了解在 Ruby 中与 lambda 一起使用的 inject 行为 - 2

    我经常将预配置的lambda插入可枚举的方法中,例如“map”、“select”等。但是“注入(inject)”的行为似乎有所不同。例如与mult4=lambda{|item|item*4}然后(5..10).map&mult4给我[20,24,28,32,36,40]但是,如果我制作一个2参数lambda用于像这样的注入(inject),multL=lambda{|product,n|product*n}我想说(5..10).inject(2)&multL因为“inject”有一个可选的单个初始值参数,但这给了我......irb(main):027:0>(5..10).inject

  7. ruby 变量作为同一对象(指针?) - 2

    >>a=5=>5>>b=a=>5>>b=4=>4>>a=>5如何将“b”设置为实际的“a”,以便在示例中,变量a也将变为4。谢谢。 最佳答案 classRefdefinitializeval@val=valendattr_accessor:valdefto_s@val.to_sendenda=Ref.new(4)b=aputsa#=>4putsb#=>4a.val=5putsa#=>5putsb#=>5当您执行b=a时,b指向与a相同的对象(它们具有相同的object_id).当你执行a=some_other_thing时,a将指向

  8. ruby - 奇怪的 ruby​​ for 循环行为(为什么这样做有效) - 2

    defreverse(ary)result=[]forresult[0,0]inaryendresultendassert_equal["baz","bar","foo"],reverse(["foo","bar","baz"])这行得通,我想了解原因。有什么解释吗? 最佳答案 如果我使用each而不是for/in重写它,它看起来像这样:defreverse(ary)result=[]#forresult[0,0]inaryary.eachdo|item|result[0,0]=itemendresultendforainb基本上就

  9. ruby-on-rails - 这个 C 和 PHP 程序员如何学习 Ruby 和 Rails? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它

  10. ruby - 比较 rspec 中的 float 时的奇怪行为 - 2

    以下测试中的第3个失败:specify{(0.6*2).shouldeql(1.2)}specify{(0.3*3).shouldeql(0.3*3)}specify{(0.3*3).shouldeql(0.9)}#thisonefails这是为什么呢?这是浮点问题还是ruby​​或rspec问题? 最佳答案 从rspec-2.1开始specify{(0.6*2).shouldbe_within(0.01).of(1.2)}在那之前:specify{(0.6*2).shouldbe_close(1.2,0.01)}

随机推荐