比较数组中的值与同一数组中的其他值

8
我所要实现的是循环遍历数组,然后查看数组中的项目是否在三个方面相同:产品ID、大小值和颜色值。我想创建一个新的数组,其中列出了项目,我不想保留重复的值。如果这些重复的值在这三个点上相同,则希望将它们的数量合并计算。比如说,如果我有3个相同的产品ID、相同大小和颜色的项目,并且我已经在我的新数组中订购了这3个项目,那么这个项目只会显示一次,数量将为9。因此,在我的新数组中将不会有重复的值。
当前循环:
foreach($orders as $key => $order){
            foreach($order['orderProducts'] as $key => $value){
                echo '<pre>';
                print_r($value['attributes']);
                echo '</pre>';
            }
 }

以下是数组的结果。
Array
(
    [id] => 2
    [product_id] => 4
    [order_id] => 2
    [name] => swag3
    [description] => haha
    [price] => 19.95
    [proceeds] => 10.00
    [quantity] => 2
    [attributes] => [{"id":1,"name":"Size","value":"XS","active":1},{"id":8,"name":"Color","value":"Wit","active":1}]
)
Array
(
    [id] => 3
    [product_id] => 3
    [order_id] => 3
    [name] => swag2
    [description] => lol
    [price] => 19.95
    [proceeds] => 10.00
    [quantity] => 2
    [attributes] => [{"id":2,"name":"Size","value":"S","active":1},{"id":7,"name":"Color","value":"Zwart","active":1}]
)
Array
(
    [id] => 4
    [product_id] => 3
    [order_id] => 4
    [name] => swag2
    [description] => lol
    [price] => 19.95
    [proceeds] => 10.00
    [quantity] => 1
    [attributes] => [{"id":2,"name":"Size","value":"S","active":1},{"id":7,"name":"Color","value":"Zwart","active":1}]
)

我正在寻找的类型...

(这是我想要的类型...)
Array
(
    [id] => 2
    [product_id] => 4
    [order_id] => 2
    [name] => swag3
    [description] => haha
    [price] => 19.95
    [proceeds] => 10.00
    [quantity] => 2
    [attributes] => [{"id":1,"name":"Size","value":"XS","active":1},{"id":8,"name":"Color","value":"Wit","active":1}]
)
Array
(
    [id] => 3
    [product_id] => 3
    [order_id] => 3
    [name] => swag2
    [description] => lol
    [price] => 19.95
    [proceeds] => 10.00
    [quantity] => 3
    [attributes] => [{"id":2,"name":"Size","value":"S","active":1},{"id":7,"name":"Color","value":"Zwart","active":1}]
)

解决方案 注意这是采用 Blade PHP 作为前端。

后端

$order // is the array with products
$items = [];
foreach($orders as $key => $order){
    foreach($order['orderProducts'] as $op){
        $i = [
        'product'=> Product::findOrFail($op->product_id)->toArray(),
        'attributes' =>$op->attributes,
        'quantity'=>$op->quantity
        ];
        $matchedResult = false;
        $count = count($items);
        for($a = 0; $a < $count; $a++){
            // Items with the same product_id in the $item array
            if($items[$a]['product']['id'] == $i['product']['id']){
                //check if the attributes are also the same
                if($items[$a]['attributes'] === $i['attributes']){
                    // The attributes ar ethe same so up the quantity
                    $items[$a]['quantity'] += $i['quantity'];
                    $matchedResult = true;
                    continue; // If its right there are no other matches
                }
            }
        }
        if($matchedResult === false){
            // only push item if there is not a match.
            $items[] = $i;
        }
    }
}

前端

<div class="table-responsive">
  <table class="table table-striped">
    <thead>
      <tr>
        <th>Product</th>
        <th>quantity</th>
      </tr>
    </thead>
    <tbody>
    @foreach($items as $item)
    <tr>
      <td>{{$item['product']['name']}}
      @if(count($item['attributes']) > 0) <small>
      @foreach($item['attributes'] as $att)
      {{$att['name']}} - {{$att['value']}}
      @endforeach
      </small>
      @endif</td>
      <td>{{$item['quantity']}}</td>
    </tr>
    @endforeach
    </tbody>
  </table>
</div>

没有内置的函数可以实现这个功能。你必须编写自己的循环来实现它。 - Barmar
@Barmar:是的,刚刚重新阅读了一遍。 - AbraCadaver
你需要将那个属性的JSON对象取出来,并将元素添加到另一个相关的表中。如果现在就这样做,你会为自己省去很多麻烦。 - AbraCadaver
如果这些数据来自数据库,请注意整个过程可以通过简单的SQL查询实现。 - RandomSeed
使用SELECT DISTINCT product_id,attributes语句可以更快地获取数据,而不必检索所有记录并删除未使用的数据。 - vivek s vamja
显示剩余2条评论
6个回答

8

您可以不使用嵌套循环来实现目标。您可以使用product_id、size和color参数的哈希函数值,并将该值用作新数组键,如下所示:

$orders = // original array;
$newOrders = [];     // new array

foreach($orders as $order) {
    $pi = $order["product_id"];                // get product_id
    $attr = json_decode($order["attributes"]); // get attributes:
    $size = $attr[0]->value;                   // get size value
    $color = $attr[1]->Color;                  // get color

    $hash = sprintf("%s.%s.%s", $pi, $size, $color); // Calculate hash

    if ($newOrders[$hash]) {
        $newOrders[$hash].quantity++; // If hash is already present then just increase quantity
    } else {
        // Otherwise add new order
        $newOrders[$hash] = [
            "order" => $order,
            "quantity" => 1
        ];
    }
}

2
我希望这可以帮助你:
        $sortedArray = [];
        foreach ($order as $array) {
            $tag = getTag($array);
            push_to_array($sortedArray,$array,$tag);
        }



        function push_to_array(&$array1,$array2,$tag)
        {
            isset($array1[$tag]) ? $array1[$tag]['quantity'] += $array2['quantity'] : $array1[$tag] = $array2;
        }
        function getTag($array)
        {
            $attribs = json_decode($array['attributes'],true);
            foreach ($attribs as $value) {
                ($value['name'] =='Size' ) && $size = $value['value'];
                ($value['name'] =='Color') && $color= $value['value'];
            }
            return $array['product_id'].$size.$color;
        }

0

试试这个(未经测试但逻辑应该是正确的):

$orders = // original array;
$new;     // new array

foreach($orders as $order) {
    $pi = $order["product_id"];                // get product_id
    $attr = json_decode($order["attributes"]); // get attributes:
    $size = $attr[0]->value;                   // get size value
    $color = $attr[1]->Color;                  // get color
    $duplicate = false;
    foreach($newOrders as $newOrder() {        // loop through nested array
        $newPi = $newOrder["product_id"];
        $newAttr = json_decode($newOrder["attributes"]);
        $newSize = $newAttr[0]->value;
        $newValue = $newAttr[1]->Color;

        // check to see if same
        if(
            $pi == $newPi &&
            $size == $newSize &&
            $color == $newColor
        ) {
            $newOrders["quantity"]++;
            $duplicate = true;
            break;
        }
    }
    if(!$duplicate) {
        $new[] = $order;
    }
}

编辑:抱歉,我刚刚重新阅读了您的帖子,看到您不想要完整的解决方案。很抱歉。但我希望这可以向您展示嵌套循环是解决此问题的方法。如评论中所述,在PHP中没有内置函数可以实现此功能(据我所知)。


0
这并不是一个解决方案,而是通过面向对象编程让你思考的另一种方法。它将在当前和下一个问题中对你有很大帮助。
现在,你有一个业务案例需要在你的业务层中解决。 如果你想,我可以帮你解决。
<?php

class Attribute {
    private $_id;
    private $_name;
    private $_value;
    private $_active;

    // TODO implement getter and setter 
    // lTODO implement constructor
}

class Product {
    private $_id;
    private $_productId;
    // ... order_id, name, ...
    private $_attribute_a = array(); // it will be an array of attribute's object

    // TODO implement getter and setter 
    // TODO implement constructor

    private function getAttributeByName($name) {
        // loop through attribute array object and return the right attribute
        // foreach ($this->_attribute_a as $attr) {
        //      if ($attr->name === $name) return $attr;
        // }
    }

    public function equals($o) {
        if (!is_a($o, 'Product'))   return FALSE;
        if ($this == $o)            return TRUE ;

        if ($this->_productId === $o->_productId) {
            $attr1 = $this->getAttributeByName('Size');
            $attr2 = $this->getAttributeByName('Size');
            if ($attr1->getValue() !== $attr2->getValue()) return FALSE; 

            $attr1 = $this->getAttributeByName('Color');
            $attr2 = $this->getAttributeByName('Color');
            if ($attr1->getValue() !== $attr2->getValue()) return FALSE; 
            return TRUE;
        }
        return FALSE;
    }
}

现在,您可以轻松比较两个产品对象,并且以后更新equals()不会对您的代码产生影响。

0

你已经从其他用户那里得到了一些很好的答案。

然而,我想为那些正在规划阶段的谷歌用户或其他用户以及您自己的知识发布此帖子。

以您的示例为例,您正在使用一个购物篮。您不应该在数组中有重复的项目,而应该在项目上使用数量度量,并在添加到数组之前检查数组是否存在匹配项并增加数量。

如果按照您当前的方式处理代码,那么如果我要添加20个相同的项目,您当前的系统每次打开购物篮时都会有一个包含20个元素的数组需要遍历,这没有任何好处。

这种其他方法还将为您提供支持,使人们可以一次添加多个项目的数量,在您的购物篮页面上编辑数量。


-1
请注意代码下面的假设。
function combineDuplicates($orders) {
$indexArray = array();
$uniqueArray = array();
foreach($orders as $value) {
    $productID = $value['product_id'];
    $attributes = $value['attributes'];
    foreach($attributes as $attribute) {
        switch($attribute['name']) {
            case 'Size' :   $size = $attribute['value'];
                            break;
            case 'Color':   $color = $attribute['value'];
                            break;
            default : break;
        }
    }
    if (!isset($indexArray[$productID][$size][$color])) {
        $indexArray[$productID][$size][$color]['count'] = 0;
        $uniqueArray[] = $value;
    }
    $indexArray[$productID][$size][$color]['count']++;
}
$orders = array();
foreach($uniqueArray as $key => $value) {
    $productID = $value['product_id'];
    $attributes = $value['attributes'];
    foreach($attributes as $attribute) {
        switch($attribute['name']) {
            case 'Size' :   $size = $attribute['value'];
                            break;
            case 'Color':   $color = $attribute['value'];
                            break;
            default : break;
        }
    }
    $uniqueArray[$key]['quantity'] = $indexArray[$productID][$size][$color]['count'];
}
return $uniqueArray;
}

假设:

  • 'attributes' 被转换为关联数组
  • 每个元素中的 product_id、颜色和尺寸值均非空

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接