【问题标题】:Find max and min key in associative array在关联数组中查找最大和最小键
【发布时间】:2012-11-03 18:39:23
【问题描述】:

我有像

这样的关联数组
array
{
    [company 1]=>array
                      (
                        [1981] => 1
                        [1945] => 3
                      )
   [company 2]=>array
                    (
                       [1990] => 18
                       [2005] => 13
                    )
   [company 3]=>array
                    (
                       [1950] => 6
                       [2012] => 9
                    )
}

我想获得最低和最高的密钥,即 1945 和 2012。 我怎样才能做到这一点?我已经搜索过 stackoverflow,Hightest value of an associative array 是最接近的可能性,但它给出了最小值和最大值,我想要最小值和最大值键。

**我不想使用 foreach 循环 **

【问题讨论】:

  • “我不想使用 foreach 循环”这个任意要求是怎么回事?
  • 我的结果数组非常大,因此在使用 foreach 递归和构建新数组时会消耗大量时间。而如果可以使用 min 或 max 函数来做到这一点,那将是非常有益的。
  • -1 表示任意限制,禁止为此类工作制作的工具。事实上,需求将这个问题带到了“过于本地化”和“没有建设性”的交叉点。
  • @cHao 我认为这可以使用 array_keys、min、max、array_map 函数来完成......我只是不知道如何......这就是我在这里问的原因......我已经告诉了我的原因避免在以前的commnet中使用foreach ..
  • @Deadlock:你的理由无效。无论如何,您将不得不遍历整个数组(以及其中的每个数组,除非您已经对子数组进行了排序)。这些都不需要创建新数组。不过有趣的是:如果您使用 array_keys 或 array_map,无论如何您都在创建一个新数组。

标签: php arrays associative-array


【解决方案1】:

如果你真的讨厌foreach,这里有一个解决方案:

$arr = array(
  "Company 1" => array(
    "1981" => 1,
    "1945" => 3
  ),

  "Company 2" => array(
    "1990" => 18,
    "2005" => 13
  ),

  "Company 3" => array(
    "1950" => 6,
    "2012" => 9
  )
);


$arr = array_map("array_keys", $arr);
$arr = array_reduce($arr, "array_merge", array());

你的$arr 最终会是这样的:

Array
(
    [0] => 1981
    [1] => 1945
    [2] => 1990
    [3] => 2005
    [4] => 1950
    [5] => 2012
)

现在您可以使用min() 和max() 函数或sort() 轻松获得最高和最低值。

sort($arr);
echo end($arr); /*highest value; actual output: 2012*/
echo reset($arr); /*lowest value; actual output: 1945*/

【讨论】:

    【解决方案2】:

    试试这个:
    使用 foreach。

            $array = array("company 1" => array(1981 => 1, 1945 =>3),
                            "company 2" => array(1990 => 18, 2005 => 13),
                            "company 3" => array(1950 => 6, 2012 =>9),
            );
    
            $keys = array();
            foreach($array as $arr)
            {
                foreach( array_keys($arr) as $val)
                {
                    array_push($keys, $val);
                }
            }
            sort($keys);
            $min = $keys[0];
            $max = $keys[count($keys)-1];
    

    没有foreach:

            global $keys;
            $GLOBALS['keys'] = array();
            function sortme($arr)
            {
                is_array($arr)? array_map("sortme",array_keys($arr)): array_push($GLOBALS['keys'], $arr);
    
            }
            array_map("sortme",$array);
            sort($GLOBALS['keys']);
            $min = $GLOBALS['keys'][0];
            $max = $GLOBALS['keys'][count($GLOBALS['keys'])-1];
            echo "min = ".$min . "<br/>max = ".$max;
    

    【讨论】:

    • 我已经提到过我不想使用 foreach 循环。
    【解决方案3】:
    ksort($array);
    $min = reset($array);
    end($array);
    $max = key($array);
    

    编辑: 这适用于简单的数组。您有 2 级结构,因此几乎不可能避免循环通过它。

    但是,如果您的条目太多以至于 foreach 都太慢,那么您可能应该重新考虑您的方法。比如把这个列表放到数据库里,用 SQL 帮你做繁重的工作。

    具体如何?设置 MySQL 或 PostgreSQL 实例(我个人更喜欢 Postgres,原因有很多),创建数据库,创建结构如下的表:

    CREATE TABLE mytable (
        mytable_id INTEGER PRIMARY KEY,
        company VARCHAR(16),
        year INTEGER,
        value INTEGER,
        -- put some more metadata...
    )
    

    从技术上讲,您应该规范化您的数据库并为每个对象创建单独的表(例如公司表、客户表、订单等...),但您可以稍后再做。

    在您要搜索的列(如年份、公司等)上创建索引:

    CREATE INDEX mytable_year_idx ON mytable (year);
    ...
    

    最后,在您的 PHP 脚本中,连接到数据库并查询您想要的内容,如下所示:

    SELECT min(year) AS min_year,
           max(year) AS max_year
    FROM mytable
    

    【讨论】:

    • 这适用于简单的数组。您有 2 级结构。您仍然需要遍历公司,然后对于每个公司条目,您可以使用此过程获取本地最小值和最大值
    • 如果你有这么多的条目,甚至 foreach 都太慢了,也许你应该重新考虑你的方法。比如把这个列表放到数据库里,用SQL帮你做繁重的工作
    【解决方案4】:

    因为您的输入数组“非常大”并且“消耗 [a] 很多时间”,这正是使用一组简单的语言结构一次性迭代数据集。

    使用多个数组函数可能看起来更简洁或更聪明,但它们会多次传递数据,并且总是会占用比绝对必要更多的资源。

    因为您的数据处理的是年份,所以您可以使用“幻数”将业务逻辑构建到代码逻辑中——假设您永远不会遇到负年份或 10,000 及以上的年份。

    如果您想要一种更加与业务无关的方法,您可以通过将第一行移出输入数组并获取该子数组的最小和最大键来植入默认的最小值和最大值。

    幻数代码:(Demo)

    $minYear = 9999;
    $maxYear = 0;
    foreach ($array as $row) {
        foreach ($row as $year => $value) {
            if ($year > $maxYear) {
                $maxYear = $year;
            }
            if ($year < $minYear) {
                $minYear = $year;
            }
        }
    }
    echo "MinYear = $minYear, MaxYear = $maxYear";
    // MinYear = 1945, MaxYear = 2012
    

    移动默认代码:(Demo)

    if ($array) {
        $firstKeys = array_keys(array_shift($array));
        $minYear = min($firstKeys);
        $maxYear = max($firstKeys);
    } else {
        $minYear = null;
        $maxYear = null;
    }
    foreach ($array as $row) {
        foreach ($row as $year => $value) {
            if ($year > $maxYear) {
                $maxYear = $year;
            } elseif ($year < $minYear) {
                $minYear = $year;
            }
        }
    }
    echo "MinYear = $minYear, MaxYear = $maxYear";
    

    请注意,Shifted sn-p 专门处理第一个数据集以获取默认值 - 这需要一些额外的行 - 但由于 elseif 而具有更高的潜在效率。

    这些技术都不使用迭代函数调用,因此几乎可以确保它们比函数式技术执行得更快。

    【讨论】:

      猜你喜欢
      • 2010-12-07
      • 2021-11-29
      • 2013-04-24
      • 2021-12-25
      • 2018-05-03
      • 1970-01-01
      • 2020-07-12
      • 2020-05-13
      相关资源
      最近更新 更多