我发现在PHP中(或者我可能找不到),缺少适当的
is_numeric_array($array)
函数。所以我创建了一个。问题是我认为这不好,也不知道如何改进。有什么建议吗?
我的第一个功能
function is_numeric_array($array)
{
$i = 0;
foreach ($array as $a => $b) { if (is_int($a)) { ++$i; } }
if (count($array) === $i) { return true; }
else { return false; }
}
is_numeric_array(array(0,0,0,0,0)); // true
is_numeric_array(array('str' => 1, 'str2' => 2, 'str3' => 3)); // false
示例
根据要求,我提供了一个有关如何有用的示例。
function is_numeric_array($array)
{
# Code below
}
function someFunction($array)
{
if (is_numeric_array($array))
{
$query = $array[0];
$param = $array[1];
$fetch = $array[2];
}
else
{
$query = $array['query'];
$param = $array['param'];
$fetch = $array['fetch'];
}
# Do your sql/pdo stuff here
}
# This use is the same of ...
someFunction(array(
'PDO SQL STATEMENT',
array('param1' => 1, 'param2' => 2, 'param3' => 3),
true
));
# ... this one.
someFunction(array(
'query' => 'PDO SQL STATEMENT',
'param' => array('param1' => 1, 'param2' => 2, 'param3' => 3),
'fetch' => true
));
# To choose one form instead of the other is coder's decision
# Also I know it is useless but I was just wondering why anybody actually looked forward this function
#1 楼
除了使用计数器来计算条件为真的键之外,您还可以在找到不是int的键后立即返回false,如果循环到达末尾而没有找到这样的键,则返回true: />foreach ($array as $a => $b) {
if (!is_int($a)) {
return false;
}
}
return true;
这样做的好处是它会短路(即一旦找到不是int的键,它将停止迭代)并摆脱计数器。
评论
\ $ \ begingroup \ $
array_fill(3,5,0)怎么样?您认为数字数组吗?
\ $ \ endgroup \ $
–鲁迪
2011年10月8日,12:14
\ $ \ begingroup \ $
而不是使用is_int($ a),请使用($ a!==(int)$ a),它将快10倍。
\ $ \ endgroup \ $
–布卡贝
2014年11月1日19:43
#2 楼
在@ sepp2k答案(+1)上稍作改进(删除一些工具会吐出“未使用的变量警告”):线性数组:foreach (array_keys($array) as $a)) {
if (!is_int($a)) {
return false;
}
}
return true;
或@RobertPitt的解决方案:)(也在那里+1)
但是我的要点是:
您为什么需要这个,我从来没有用过这样的东西,可能是解决方案是更改,而API设计缺陷或数据结构缺陷在某处?还没有,但是可以。
对OP的响应:
我正在为需要3键数组的查询构建db方法。如果数组是数字数组,则顺序必须是:语句,参数,提取。如果不是这样,那么编码器将指定密钥字符串,顺序可以不同,并且三个必需参数中的两个可以为空。 :)
return array_merge($array) === $array;
也许我误解了一点,但它应该弄清楚如何用另一种支票来构建它:)
my_db_function(
array("myquery", array("params", "..."), "myfetchmode")
);
// or
my_db_function(
array("params" => "myquery", "fetchmode" => "myfetchmode, "params" => array("myparams", "...) )
);
那仍然是一个很大的代码块,但是我不想缩短它,并且冒着糟糕的可读性的风险。
我要怎么做,就是创建一个my_db_stuff_param_helper($ aParams),它将始终返回一个包含3个键的数组,这些键填充有真实值(如果没有传递任何值,则为默认键) br />
function my_db_fuction($statement) {
if(isset($statement["query"])) { // Assoc 'Mode'
$query = $statement["query"];
if(isset($statement["params"])) { $params = $statement["params"]; }
else { $params = array(); }
if(isset($statement["fetchmode"])) { $fetchmode = $statement["fetchmode"]; }
else { $fetchmode = "select"; // optional param, default value here
} else if(isset($statement[0]) { // Linear Array Mode
$query = $statement[0];
if(isset($statement[1])) { $params = $statement[1]; }
else { $params = array(); }
if(isset($statement[2])) { $fetchmode = $statement[2]; }
else { $fetchmode = "select"; // optional param, default value here
} else {
// Error, misformed format
}
// Now we got our 3 variables :)
}
类似的东西“感觉”(主观,我知道)比构建通用函数进行键检查更好。 (我猜是isset($ statement [“ query”])而不是is_numeric_array我要归结为:)
评论
\ $ \ begingroup \ $
我需要它,因为我正在创建一个方法,根据它的编写方式,它必须以不同的方式表现。
\ $ \ endgroup \ $
–鞋子
2011-1-25在18:29
\ $ \ begingroup \ $
您正在做的事情迫使您去做某事,因此您需要这种方法。我是说,也许如果您做不同的事情,您将不需要它。对不起,我不知道如何使自己更清晰,但我读到您的回答为“我需要这个,因为我需要这个”,我只是建议也许您不需要:)而且由于这是codereview而不是SO i我提到了它,而不仅仅是提供(至少对我来说)显而易见的答案的代码片段:)
\ $ \ endgroup \ $
– edorian
2011年1月25日20:26
\ $ \ begingroup \ $
我明白你的意思。我正在为需要3键数组的查询构建db方法。如果数组是数字数组,则顺序必须是:语句,参数,提取。如果不是这样,那么编码器将指定键串,顺序可以不同,并且三个必需参数中的两个可以为空。我知道它很奇怪,我将对其进行编辑,但是我只是想知道是否不存在适当的功能。
\ $ \ endgroup \ $
–鞋子
2011年1月26日7:37
\ $ \ begingroup \ $
编辑我的回答作为回应,可能有点夸张了:)
\ $ \ endgroup \ $
– edorian
2011年1月26日8:33
\ $ \ begingroup \ $
没考虑过这种方法。感谢您提供它。但是,让我们面对现实,PHP有很多无用的函数,为什么不将is_numeric_array()放入内核?
\ $ \ endgroup \ $
–鞋子
11年1月27日在18:16
#3 楼
最初,我没有意识到您要检查键是否为整数。如果执行此操作的原因是要确保键分别是0、1、2、3、4等作为索引数组而不是关联数组,则可以使用以下命令:function is_numeric_array($arr)
{
return array_keys($arr) === range(0,(count($arr)-1));
}
/*
* Tests
*/
var_dump(is_numeric_array(array('a', 'b', 'c'))); // true
var_dump(is_numeric_array(array("0" => 'a', "1" => 'b', "2" => 'c'))); // true
var_dump(is_numeric_array(array("1" => 'a', "0" => 'b', "2" => 'c'))); // false
var_dump(is_numeric_array(array("a" => 'a', "b" => 'b', "c" => 'c'))); // false
要求的基准测试结果:
以下是用于测试执行情况的代码:
$array = array();
for($i=0;$i<=500000;$i++)
{
$array[] = "some_string";
}
$m_initial = memory_get_usage();
is_numeric_array($array);
$increase = memory_get_usage() - $m_initial;
您可以从上面看到,我测试了具有500K字符串的线性数组:
$increase
的值显示为65032(以字节为单位)。如果我们转换为KB,则大约是64位舍入。以KB为单位的结果显示63.507,我认为还可以。评论
\ $ \ begingroup \ $
它实际上仅检查值,而不检查键。我错了吗?
\ $ \ endgroup \ $
–鞋子
2011年1月25日18:11
\ $ \ begingroup \ $
在其中添加了$ key。
\ $ \ endgroup \ $
– RobertPitt
2011年1月25日在18:13
\ $ \ begingroup \ $
array_filter的回调仅将数组值作为参数。您需要先获取array_keys,然后对其进行过滤。
\ $ \ endgroup \ $
– Mchl
2011年1月25日18:18
\ $ \ begingroup \ $
是的,它被废弃了,我有点不太坚持,应该做我的研究。
\ $ \ endgroup \ $
– RobertPitt
2011年1月25日在18:22
\ $ \ begingroup \ $
好吧,我想第二个示例返回false,因为您作为编码器定义了一个特定的键。
\ $ \ endgroup \ $
–鞋子
2011年1月25日18:31
#4 楼
好的,这是确保一致性和正确命名约定的镜头(由于numeric
和int
意味着不同的东西,所以彼此之间毫无意义...): >现在,对于更多面向对象的方法,我将构建一个filteriterator:如果要验证,可以执行以下操作:function isNumericArray(array $array) {
foreach ($array as $a => $b) {
if (!is_numeric($a)) {
return false;
}
}
return true;
}
function isIntArray(array $array) {
foreach ($array as $a => $b) {
if (!is_int($a)) {
return false;
}
}
return true;
}
评论
\ $ \ begingroup \ $
+1和FilterIterator的区别。唯一可以改进的是仅检查数组值。无需在整个阵列上运行。
\ $ \ endgroup \ $
– kaiser
2014年3月24日在1:33
#5 楼
一旦找到一个不是int的元素,该函数就会消失,从而使该函数对大型数组更有效。评论
\ $ \ begingroup \ $
那和他的代码有什么不同?除非我缺少某些内容,否则这将检查值是否为整数,而不是键。如果键不是整数,代码也会导致错误。
\ $ \ endgroup \ $
–sepp2k
2011-1-25在16:42
\ $ \ begingroup \ $
另外,它返回$ i而不是返回$ 1。
\ $ \ endgroup \ $
–鞋子
2011-1-25在16:53
\ $ \ begingroup \ $
另外,我不确定计数是如何工作的,但是它可能会移动数组,导致您将其遍历两次。
\ $ \ endgroup \ $
– Mark Loeser
2011年1月25日在17:08
\ $ \ begingroup \ $
... while循环上也没有停止条件。变了
\ $ \ endgroup \ $
– Michael K
2011-1-25在17:27
\ $ \ begingroup \ $
我也会尝试krsort($ array,SORT_STRING);第一。这会将大多数非数字键移到数组的开头。如果可以提高性能,则需要进行基准测试。
\ $ \ endgroup \ $
– Mchl
2011-1-25在18:03
#6 楼
这可能会更有效:是整数,但是如果数组是索引的(非关联),则为此使用array_values()
可以解决问题:function is_numeric_array($array)
{
$array = array_keys($array);
if ($array === array_filter($array, 'is_int'))
{
return true;
}
return false;
}
评论
\ $ \ begingroup \ $
这应该是公认的解决方案! array_values FTW!
\ $ \ endgroup \ $
–TomášFejfar
17 Mar 29 '17 at 20:23
#7 楼
如果您实际上是在尝试确定它是否是顺序整数数组而不是关联整数,即json_encode可以将数组与对象进行比较,那么这可能是最快的方法:function is_normal_array($arr) {
$c = count($arr);
for ($i = 0; $i < $c; $i++) {
if (!isset($arr[$i])) {
return false;
}
}
return true;
}
...当然,最快的代码是您永远不会运行的代码,因此请考虑您是否真的需要这样做,并且仅在执行时使用它。
评论
\ $ \ begingroup \ $
这应该比其他人发布的foreach解决方案要快,但是算法并不一致。 foreach解决方案针对array(0 =>'a',1 =>'b',3 =>'d')返回true,而我的返回false。
\ $ \ endgroup \ $
–杰伊·帕罗林(Jay Paroline)
2011-1-27在7:24
#8 楼
这是一则古老的文章,但是如果您正在寻找一个较短但仍然优雅的解决方案,请使用此方法:太短了。干杯
评论
我只是好奇,您能为此提供用例吗?做完了,希望你喜欢它。
它们都是坏的=)这是唯一正确的方法:gist.github.com/1272230
我读的越多,我就越困惑。您似乎在确定数组是否具有关联性,而我将本主题读为“确定所有数组值是否均为数字/整数”。此处以is_assoc检查的简单方法为例:stackoverflow.com/a/173479/1695680
抱歉,经过进一步考虑,链接的答案不太可靠;您实际上想要修改下一个答案:stackoverflow.com/a/4254008/1695680以使用“ is_int”而不是“ is_string”