简体   繁体   English

在关联数组中查找最大和最小键

[英]Find max and min key in associative array

I have associative array like我有像这样的关联数组

array
{
    [company 1]=>array
                      (
                        [1981] => 1
                        [1945] => 3
                      )
   [company 2]=>array
                    (
                       [1990] => 18
                       [2005] => 13
                    )
   [company 3]=>array
                    (
                       [1950] => 6
                       [2012] => 9
                    )
}

I want to get lowest and highest key ie 1945 and 2012. How can i achieve this?我想获得最低和最高的键,即 1945 年和 2012 年。我怎样才能做到这一点? I have already searched over stackoverflow and Hightest value of an associative array is the nearest possibility but it gives out min and max value and I want min and max key.我已经搜索过 stackoverflow 并且关联数组的 Hightest 值是最接近的可能性,但它给出了最小值和最大值,我想要最小值和最大值键。

**I don't want to use foreach loop ** **我不想使用foreach循环**

If you really hate foreach , here's a solution:如果你真的讨厌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());

Your $arr would end up like this:你的$arr最终会是这样的:

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

Now you can use min() and max() functions or sort() it get the highest and lowest value easily.现在您可以使用min()max()函数或sort()轻松获得最高和最低值。

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

Try this one:试试这个:
using foreach.使用 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];

Without foreach:没有 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;
ksort($array);
$min = reset($array);
end($array);
$max = key($array);

EDIT : This works for simple array.编辑:这适用于简单数组。 You have 2 level structure, so it would be close to impossible to avoid looping through it.您有 2 级结构,因此几乎不可能避免遍历它。

However, if you have so many entries that even foreach is too slow, probably you should rethink your approach.但是,如果您有太多条目,甚至 foreach 也太慢,那么您可能应该重新考虑您的方法。 For example, put this list into database and use SQL to do heavy lifting for you.例如,将这个列表放入数据库并使用 SQL 为您完成繁重的工作。

How exactly?具体如何? Setup instance of MySQL or PostgreSQL (I personally prefer Postgres for many reasons), create database, create table with structure like this:设置 MySQL 或 PostgreSQL 实例(出于多种原因,我个人更喜欢 Postgres),创建数据库,创建具有如下结构的表:

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

Technically, you should normalize your database and create separate tables for every object (like table for companies, for customers, orders, etc...), but you can come to this later.从技术上讲,您应该规范化您的数据库并为每个对象创建单独的表(例如公司表、客户表、订单表等),但您可以稍后再讨论。

Create indexes on columns you are going to be searching on (like year, company, etc):在要搜索的列上创建索引(如年份、公司等):

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

Finally, in your PHP script, connect to database and query it for what you wanted, something like this:最后,在您的 PHP 脚本中,连接到数据库并查询您想要的内容,如下所示:

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

Because your input array is " very large " and " consumes [a] lot of time ", that is precisely a justification for using a set of simple language constructs to iterate the dataset in a single pass.因为您的输入数组“非常大”并且“消耗 [a] 很多时间”,这正是使用一组简单的语言构造在单次传递中迭代数据集的理由。

Using multiple array functions may look more concise or clever, but they will be making multiple passes over the data and invariably draw more resources than absolutely necessary.使用多个数组函数可能看起来更简洁或更聪明,但它们会对数据进行多次传递,并且总是会占用比绝对必要更多的资源。

Because your data is dealing with years, you can build business logic into the code logic with "magic numbers" -- assuming that you will never encounter a negative year or a year from 10,000 and beyond.因为您的数据处理年份,所以您可以将业务逻辑构建到带有“幻数”的代码逻辑中——假设您永远不会遇到负年份或 10,000 及以上的年份。

If you want a more business-agnostic approach, you can seed the default min and max values by shifting the first row off the input array and fetching that subarray's min and max keys.如果您想要一种与业务无关的方法,您可以通过将第一行移出输入数组并获取该子数组的最小和最大键来设定默认的最小值和最大值。

Magic Number Code: ( 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

Shifted Defaults Code: ( 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";

Notice that the Shifted snippet specifically handles the first dataset to get the defaults - which takes a few extra lines - but enjoys higher potential efficiency due to the elseif .请注意, Shifted 片段专门处理第一个数据集以获取默认值 - 这需要一些额外的行 - 但由于elseif具有更高的潜在效率。

Neither of these techniques use iterated function calls, so they are virtually assured to perform faster than functional techniques.这些技术都没有使用迭代函数调用,因此它们几乎可以保证比函数式技术执行得更快。

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

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