简体   繁体   English

如何通过键和值过滤 php 关联数组?

[英]How to filter php associative array by key and values?

I have this data:我有这个数据:

Array
(
    [0] => Array
        (
            [name] => Hair Transplantation
            [price] => € 1000 - 4000
        )

    [1] => Array
        (
            [name] => Rhinoplasty
            [price] => € 2500
        )

    [2] => Array
        (
            [name] => Otoplasty
            [price] => € 1000
        )

)

I want to filter this array by price key and, as a result, I want to be returned only one item, item with lowest price number.我想按price键过滤这个数组,因此,我只想返回一个项目,即价格最低的项目。

Thank you!谢谢!

$data = [/* your data */];
uasort($data, function($a, $b) {
    preg_match("/\d+/", $a['price'], $matchesA);
    preg_match("/\d+/", $b['price'], $matchesB);
    return (int)$matchesB[0] <=> (int)$matchesA[0];
});

$result = array_pop($data);

Added (08.08.2020) Because of vivek_23's comment, I added second solution:添加 (08.08.2020) 由于 vivek_23 的评论,我添加了第二个解决方案:

    $result = array_reduce($price, 'getMinimumPrice', null);

    function getMinimumPrice(?array $itemA, array $itemB): array
    {
        if (is_null($itemA)) {
            return $itemB;
        }
        return getPrice($itemA) < getPrice($itemB)
            ? $itemA
            : $itemB;
    }
    
    function getPrice(array $item): int
    {
        preg_match("/\d+/", $item['price'], $matches);
        return $matches[0];
    }

And also I check the speed difference:我还检查了速度差异:

$primary = [
    [
        'name' => 'Hair Transplantation',
        'price' => '€ 1000 - 4000',
    ],
    [
        'name' => 'Rhinoplasty',
        'price' => '€ 2500',
    ],
    [
        'name' => 'Otoplasty',
        'price' => '€ 1000',
    ],
    /* ... 155 items */
];

function getMinimumPrice(?array $itemA, array $itemB): array
{
    if (is_null($itemA)) {
        return $itemB;
    }
    return getPrice($itemA) < getPrice($itemB)
        ? $itemA
        : $itemB;
}

function getPrice(array $item): int
{
    preg_match("/\d+/", $item['price'], $matches);
    return $matches[0];
}

$timeRepeat = 1000;
$reduce = 0;
for ($i = 0; $i < $timeRepeat; $i++) {
    $start = microtime(true);
    $price = $primary;
    array_reduce($price, 'getMinimumPrice', null);
    $reduce += microtime(true) - $start;
}

$uasort = 0;
for ($i = 0; $i < $timeRepeat; $i++) {
    $start = microtime(true);
    $price = $primary;
    uasort($price, function($a, $b) {
        preg_match("/\d+/", $a['price'], $matchesA);
        preg_match("/\d+/", $b['price'], $matchesB);
        return (int)$matchesB[0] <=> (int)$matchesA[0];
    });
    array_pop($price);
    $uasort += microtime(true) - $start;
}

print_r([
    'uasort' => $uasort,
    'reduce' => $reduce,
    'difference' => round($uasort / $reduce, 12),
]);

My results:我的结果:

Array (
       [uasort] => 8.0096476078033
       [reduce] => 2.1610336303711
       [difference] => 3.706396557294
)

Try this:尝试这个:

$items is your base array. $items是您的基本数组。

$items = [
    0 => [
        "name" => "Hair Transplantation",
        "price" => "€ 1000 - 4000"
    ],

    1 => [
        "name" => "Rhinoplasty",
        "price" => "€ 2500"
    ],
    2 => [
        "name" => "Otoplasty",
        "price" => "€ 1000"
    ]
];

$lowestPrice = PHP_INT_MAX;
$rightKey = -1;

foreach ( $items as $key => $item )
{
    $clean = str_replace('€ ', '', $item['price']);
    $chunks = explode('-', $clean);

    if ( count($chunks) == 2 )
        $price = floatval(trim($chunks[0]));
    else
        $price = floatval(trim($clean));

    if ( $price < $lowestPrice )
    {
        $lowestPrice = $price;
        $rightKey = $key;
    }
}

$lowestItem = $items[$rightKey];

print_r($lowestItem);

EDIT: Regex version编辑:正则表达式版本

$items = [
    0 => [
        "name" => "Hair Transplantation",
        "price" => "€ 1000 - 4000"
    ],

    1 => [
        "name" => "Rhinoplasty",
        "price" => "€ 2500"
    ],
    2 => [
        "name" => "Otoplasty",
        "price" => "€ 1000"
    ]
];

$lowestPrice = PHP_INT_MAX;
$rightKey = -1;

foreach ( $items as $key => $item )
{
    $matches = [];

    if ( !preg_match('#([0-9\.]+) #', str_replace(',', '.', $item['price']), $matches) )
        continue;

    $price = floatval($matches[0]);

    if ( $price < $lowestPrice )
    {
        $lowestPrice = $price;
        $rightKey = $key;
    }
}

$lowestItem = $items[$rightKey];

print_r($lowestItem);

I don't like the data structure, as I noted in the comments on the question.正如我在对问题的评论中指出的那样,我不喜欢数据结构。 It leads to string parsing which is not ideal.它导致字符串解析不理想。

I accomplished it, however, using然而,我完成了它,使用

The following code will produce your desired result in the variable, $lowest_item .以下代码将在变量$lowest_item中产生您想要的结果。 If any of them have the same price (or same starting price), the first one that was defined will be the one returned (it could be edited to adjust which gets preference, though).如果它们中的任何一个具有相同的价格(或相同的起始价格),则定义的第一个将是返回的那个(但可以对其进行编辑以调整哪个获得偏好)。

<?php

$data = [
    [
        'name' => 'Hair Transplantation',
        'price' => '€ 1000 - 4000',
    ],
    [
        'name' => 'Rhinoplasty',
        'price' => '€ 2500',
    ],
    [
        'name' => 'Otoplasty',
        'price' => '€ 1000',
    ],
];


$lowest_item = array_reduce($data, function ($carry, $item) {
    $return_to_next = null;

    if (!$carry) {
        $return_to_next = $item;
    } else if ($carry['price'] === $item['price']) {
        $return_to_next = $carry;
    } else {
        preg_match_all('/\d+/', $carry['price'], $carry_prices, PREG_PATTERN_ORDER);
        preg_match_all('/\d+/', $item['price'], $item_prices, PREG_PATTERN_ORDER);

        $carry_compare = min($carry_prices[0]);
        $item_compare = min($item_prices[0]);

        if ($carry_compare <= $item_compare) {
            $return_to_next = $carry;
        } else {
            $return_to_next = $item;
        }
    }

    return $return_to_next;
});
$people = array(
    0 => array(
      'name' => 'Hair Transplantation',
      'price' => '€ 1000 - 4000'
    ),
    1=> array(
      'name' => 'Rhinoplasty',
      'price' => '€ 2500'
    ),
    2=> array(
        'name' => 'Otoplasty',
        'price' => '€ 1000'
    )
);

$price = array_map(function($value) {
    if (strpos($value, '-') !== false) {
        $value = explode("-", $value)[0];
    }
    list($symbol, $price) = sscanf($value,'%[^0-9]%s');
    return intval($price);
}, array_column($people, 'price'));

$found_key = array_search(min($price),$price);

print_r($people[$found_key]) ;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM