【问题标题】:PHP - Find an object by key in an array of objects, update its valuePHP - 在对象数组中按键查找对象,更新其值
【发布时间】:2019-04-01 02:43:09
【问题描述】:

我有一个对象数组,并且想要更新其中一个对象的属性。

$objs = [ 
    ['value' => 2, 'key' => 'a'], 
    ['value' => 3, 'key' => 'b'] ,
];

假设我想将带有 'key'=>'a' 的对象的 'value' 设置为 5。

除了遍历数组搜索键之外,还有什么更快/更有效的方法吗?

谢谢。

编辑:关于为什么我不能使用关联数组存在争议。因为这个数组是从 JSON 值中获取的。

如果我的 JSON 对象是这样的:

"obj": {
    "a": {
        "key": "a", 
        "value": 2
    }, 
    "b": {
        "key": "b", 
        "value": 3
    }
}

不能保证对象的顺序会被保留,这是必需的。

因此,我需要在每个对象中都有一个索引,以便能够使用usort() 对其进行排序。所以我的 JSON 需要是:

"obj": {
    "a": {
        "key": "a", 
        "value": 2, 
        "index": 1
    }, 
    "b": {
        "key": "b", 
        "value": 3, 
        "index": 2
    }
}

但我不能在对象上使用usort(),只能在数组上使用。所以我的 JSON 需要是

"obj": [
    {
        "key": "a", 
        "value": 2, 
        "index": 1
    }, {
        "key": "b", 
        "value": 3, 
        "index":2
    }
]

这让我们想到了最初的问题。

【问题讨论】:

  • 好吧,如果数组的形成方式与此不同 -> ['a' => $obj] 您只需要检查它是否已设置并设置值:if(isset($objs['a']))$objs['a']['value'] = $value;
  • 我以前也有过,但是由于这个数组是由 JSON 组成的,所以不尊重对象的顺序。所以我必须为每个对象添加一个索引,以及它的值和键。
  • 您的 json 无效。发布一些有用的东西
  • 在我看来,您的问题已经在很多方面得到了解决;选择任何一个并将您的应用程序的逻辑调整为您选择的解决方案。所以改变它,例如,向对象添加一个order 字段。目前尚不清楚您想从社区中得到什么)
  • @Andreas 怎么无效?除非您在第一种情况下谈论“价值”周围缺少的引号,否则这是一个很容易修复的错字。但是你的回答对我有帮助,所以我会接受它作为正确的方法。谢谢。

标签: php object


【解决方案1】:

我想建议您重新组织您的阵列湖:

$objs = [ 
'a' => ['value'=>2, 'key'=>'a'], 
'b' => ['value'=>3, 'key'=>'b'] 
];

现在

if( array_key_exists( 'a', $objs )) {
  $objs ['a'] ['value'] = 5;
}

我一开始就是这样。但我需要对象有一个 索引值,所以我可以在主数组上运行 usort() 。这是 因为数组来自原始顺序不是的 JSON 尊重

然后创建一个index数组:

// When fill `$objs` array
$objs = [];
$arrIndex = [];
$idx = 0;
foreach( $json as $item ) {
  $arrIndex [ $item ['key']] = $idx;
  $objs [$idx ++] = $item;
}

// And your task:

if( array_key_exists( 'a', $arrIndex )) {
  $objs [ $arrIndex ['a']] ['value'] = 5;
}

【讨论】:

  • 我一开始就是这样。但是我需要对象中有一个索引值,所以我可以在主数组上运行 usort() 。这是因为数组来自不遵守原始顺序的 JSON。
  • @fractal5 我不明白你在说什么。所有数组都有索引或关联键。看来您正试图在这里获得另一个问题的答案。
  • @Andreas 不,他的意思是不能使用 key 字段作为数组的索引。
  • 但是没有解释为什么。我没有看到他不能使用它的任何充分理由。
  • 我更改了上面的代码。那个怎么样?当然@Andreas 是对的:没有足够的数据))))
【解决方案2】:

通过使用array_column(),您可以提取数组中索引为key 的所有值。然后您可以使用array_search() 找到值a 的第一次出现。这只会返回找到值的第一个索引。然后您可以简单地替换该值,因为您现在拥有该值的索引。

$keys = array_column($objs, 'key');
$index = array_search('a', $keys);

if ($index !== false) {
    $objs[$index]['value'] = 5;
}

看到这个live demo

【讨论】:

  • 请注意,如果未找到 array_search 会返回 false,这会弄乱数组。 3v4l.org/Lc2Dd p.s.这是 OP 想要更新的值而不是密钥。
  • 关于array_search() 返回false,您是绝对正确的。也就是说,这将更新它的值,而不是键(你也可以在演示中看到)。
  • 它确实更新了“键”,而不是值。正如您在我的演示中看到的那样,它更新了错误的项目。它不应该在我的示例中更新任何内容,但它会更新“key a”
  • 哎呀,我对索引名称key/value 感到困惑,它们实际上是键和值。我会更新它。谢谢!
  • 成本与 for 循环相同?
【解决方案3】:

除了遍历数组搜索键之外,还有 有什么更快/更有效的方法吗?

无论哪种方式,您都必须为迭代付出代价。

您可以在您的集合中搜索感兴趣的对象(需要线性时间),或者您可以形成某种字典数据结构,例如哈希表(需要线性时间),然后在恒定时间内找到感兴趣的对象。

这里没有免费的午餐。

【讨论】:

    【解决方案4】:

    您可以使数组与数组列相关联。这样你就可以直接赋值了。

    $objs = [ ['value'=>2, 'key'=>'a'], ['value'=>3, 'key'=>'b'] ];
    $objs = array_column($objs, null, "key");
    $objs['a']['value'] = 5;
    

    https://3v4l.org/7tJl0

    【讨论】:

    • 这比在数组上循环并在遇到对象时更新如何“更有效”?
    猜你喜欢
    • 2016-09-21
    • 2022-12-01
    • 2023-01-17
    • 2020-07-22
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多