Почему array_count_values ​​молча превращает строки в int? [Дубликат]

Я просто новичок здесь, поэтому, может быть, это просто удача, если я нашел это:

После попытки запустить скрипт из приглашения интерпретатора >>> с помощью команды

    execfile('filename.py')

, для которого я получил «NameError: name« execfile », не определен» Я попробовал очень простой

    import filename

, он работал хорошо: -)

Надеюсь, это может быть полезной и поблагодарить всех за отличные подсказки, примеры и все те мастерски прокомментированные фрагменты кода, которые являются большим вдохновением для новичков!

Я использую Ubuntu 16.014 LTS x64. Python 3.5.2 (по умолчанию, 17 ноября 2016, 17:05:23) [GCC 5.4.0 20160609] на linux

90
задан Dogbert 4 November 2010 в 20:30
поделиться

11 ответов

Нет; Нет, это не так:

Из руководство :

Ключ может быть целым или строковым. Если ключ является стандартным представлением целого числа, он будет интерпретироваться как таковой (т.е. «8» будет интерпретирован как 8, а «08» будет интерпретирован как «08»).

Добавление

Из-за комментариев ниже я подумал, что было бы интересно отметить, что поведение похоже , но не идентично для объекта JavaScript клавиш.

foo = { '10' : 'bar' };

foo['10']; // "bar"
foo[10]; // "bar"
foo[012]; // "bar"
foo['012']; // undefined!
71
ответ дан Hamish 21 August 2018 в 22:45
поделиться

У меня возникла проблема с объединением массивов, в которых были как строковые, так и целые ключи. Было важно, чтобы целые числа также обрабатывались как строка, поскольку они были именами для полей ввода (как в размерах обуви и т. Д.).

Когда я использовал $data = array_merge($data, $extra);, PHP «переупорядочил» ключи. При попытке выполнить упорядочение целые ключи (я пытался с 6 - '6' - "6" даже (string)"6" в качестве ключей) получил переименование от 0 до n ... Если вы думаете об этом, в В большинстве случаев это было бы желательным поведением.

Вы можете обойти это, используя $data = $data + $extra;. Довольно прямо, но я не думал об этом сначала ^^.

0
ответ дан Brainfeeder 21 August 2018 в 22:45
поделиться
  • 1
    Точно такая же проблема привела меня к этой странице, но я должен сказать, что это не ответ на вопрос ОП. – Flimm 19 April 2016 в 11:50
  • 2
    @Flimm True. Но поиск ответа привел меня на эту страницу. Я решил, что мое решение может помочь другим гуглерам :) – Brainfeeder 19 April 2016 в 11:53

Да, это возможно с помощью массива-casting объекта stdClass:

$data =  new stdClass;
$data->{"12"} = 37;
$data = (array) $data;
var_dump( $data );

Это дает вам (до версии PHP 7.1):

array(1) {
  ["12"]=>
  int(37)
}

( Обновление: мой оригинальный ответ показал более сложный способ, используя json_decode() и json_encode(), который не нужен.)

Обратите внимание на комментарий: К сожалению, невозможно напрямую ссылаться на значение: $data['12'] вы получите уведомление.

Обновление: из PHP 7.2 на нем также можно использовать числовую строку в качестве ключа для ссылки на значение:

var_dump( $data['12'] ); // int 32
28
ответ дан David 21 August 2018 в 22:45
поделиться
  • 1
    Однако прямой доступ к значению с помощью строкового ключа не работает. Добавьте эту строку в свой пример: echo $data['12'];. Он выдаст ошибку, «Примечание: неопределенное смещение: 12 in-on line 5». – L S 29 May 2016 в 09:47
  • 2
    Да, ты прав. Предполагая, что это возможно иногда в прошлом. – David 1 June 2016 в 11:55
  • 3
    когда U использует laravel dd ($ data), он сработает: P – Kamil Kiełczewski 28 February 2017 в 23:41
  • 4
    Упрощение для прохладного решения, но это относительно сложно, и я боюсь, что как только какой-нибудь бозо, который может что-то сделать, замечает ответ, он будет отмечен как ошибка. – LGT 11 March 2017 в 13:44
  • 5
    В PHP 7.2.0RC2 поведение такое же, как и раньше. – dev0 19 September 2017 в 14:41
  • 6
    – Don't Panic 29 August 2018 в 23:15

У меня возникла эта проблема, пытаясь отсортировать массив, в котором мне нужен ключ сортировки, который будет шестнадцатеричным sha1. Когда полученное значение sha1 не имеет букв, PHP превращает ключ в целое. Но мне нужно было отсортировать массив по относительному порядку строк. Поэтому мне нужно было найти способ заставить ключ быть строкой, не меняя порядок сортировки.

Глядя на диаграмму ASCII ( https://en.wikipedia.org/wiki/ASCII ), восклицательный знак сортируется примерно так же, как и пространство, и, конечно, ниже всех чисел и буквы.

Итак, я добавил восклицательный знак в конце ключевой строки.

for(...) {

    $database[$sha.'!'] = array($sha,$name,$age);
}

ksort($database);
$row = reset($database);
$topsha = $row[0];
-1
ответ дан drchuck 21 August 2018 в 22:45
поделиться
  • 1
    Так вы говорите, что невозможно использовать цифровую строку типа «123»? как ключ в массиве PHP, без преобразования его в целое число? – Flimm 19 April 2016 в 11:52
  • 2
    Нет - он обрабатывает ключ, который является всеми числами как целое число при сортировке массива с помощью ksort () - он никогда не преобразуется в целое число - просто сравнивается как один во время сортировки. – drchuck 20 April 2016 в 18:14

Я столкнулся с этой проблемой в массиве с ключами «0» и «». Это означало, что я не мог проверить ключи массива с помощью == или ===.

$array=array(''=>'empty', '0'=>'zero', '1'=>'one');
echo "Test 1\n";
foreach ($array as $key=>$value) {
    if ($key == '') { // Error - wrongly finds '0' as well
        echo "$value\n";
    }
}
echo "Test 2\n";
foreach ($array as $key=>$value) {
    if ($key === '0') { // Error - doesn't find '0'
        echo "$value\n";
    }
}

Обходной путь заключается в том, чтобы использовать ключи массива обратно в строки перед использованием.

echo "Test 3\n";
foreach ($array as $key=>$value) {
    if ((string)$key == '') { // Cast back to string - fixes problem
        echo "$value\n";
    }
}
echo "Test 4\n";
foreach ($array as $key=>$value) {
    if ((string)$key === '0') { // Cast back to string - fixes problem
        echo "$value\n";
    }
}
0
ответ дан fisharebest 21 August 2018 в 22:45
поделиться

В качестве обходного пути вы можете закодировать PHP-массив в json-объект с помощью опции JSON_FORCE_OBJECT.

, т. е. Этот пример:

     $a = array('foo','bar','baz');
     echo "RESULT: ", json_encode($a, JSON_FORCE_OBJECT);

приведет к:

     RESULT: {"0" : "foo", "1": "bar", "2" : "baz"}
1
ответ дан GigiManco 21 August 2018 в 22:45
поделиться

Что касается решения @david, обратите внимание, что при попытке доступа к строковым значениям в ассоциативном массиве номера не будут работать. Я предполагаю, что они отлиты целыми числами за кулисами (при доступе к массиву), и никакое значение не найдено. Доступ к значениям в виде целых чисел также не будет работать. Но вы можете использовать array_shift () для получения значений или итерации массива.

$data = new stdClass;
$data->{"0"} = "Zero";
$data->{"1"} = "One";
$data->{"A"} = "A";
$data->{"B"} = "B";

$data = (array)$data;

var_dump($data);
/*
Note the key "0" is correctly saved as a string:
array(3) {
  ["0"]=>
  string(4) "Zero"
  ["A"]=>
  string(1) "A"
  ["B"]=>
  string(1) "B"
}
*/

//Now let's access the associative array via the values 
//given from var_dump() above:
var_dump($data["0"]); // NULL -> Expected string(1) "0"
var_dump($data[0]); // NULL (as expected)
var_dump($data["1"]); // NULL -> Expected string(1) "1"
var_dump($data[1]); // NULL (as expected)
var_dump($data["A"]); // string(1) "A" (as expected)
var_dump($data["B"]); // string(1) "B" (as expected)
0
ответ дан Nico Schefer 21 August 2018 в 22:45
поделиться

Если вам нужно использовать числовой ключ в структуре данных php, объект будет работать. И объекты сохраняют порядок, поэтому вы можете выполнять итерацию.

$obj = new stdClass();
$key = '3';
$obj->$key = 'abc';
11
ответ дан steampowered 21 August 2018 в 22:45
поделиться
  • 1
    Это очень хорошее предложение. Я пишу код рамки и сталкиваюсь с кем-то, проходящим массив, который может иметь и «случайный». indexing: array ('this', 'that') или "ассоциативный" indexing: array (123 = & gt; array ('this', 'that')). Теперь, благодаря вам, я могу просто набрать x;) +1 – Just Plain High 8 December 2013 в 11:09
  • 2
    Но возможно ли использовать цифровую строку типа «123». как ключ в массиве PHP, без преобразования его в целое число? – Flimm 19 April 2016 в 11:45
  • 3
    @Flimm нет, что невозможно, поэтому я предлагаю свое решение. – steampowered 19 April 2016 в 12:21
  • 4
    Как насчет этого решения: stackoverflow.com/a/35180513/247696 – Flimm 19 April 2016 в 12:23
  • 5
    @Flimm, этот ответ, похоже, противоречит руководству PHP : Строки, содержащие действительные целые числа, будут отлиты от целочисленного типа. Например. ключ "8" фактически будет храниться под 8. С другой стороны, "08" не будет отличен, так как он не является допустимым десятичным целым. , хотя я не проверял его ответ. – steampowered 19 April 2016 в 13:04

Вы можете вывести ключ в строку, но в конечном итоге он будет преобразован в целое число из-за неправильной настройки PHP. Посмотрите сами:

$x=array((string)123=>'abc');
var_dump($x);
$x[123]='def';
var_dump($x);

Из руководства PHP:

Ключ может быть целым или строковым. Если ключ является стандартным представлением целого числа, он будет интерпретироваться как таковой (т. Е. «8» будет интерпретироваться как 8, а «08» будет интерпретироваться как «08»). Поплавки в ключе усекаются до целого. Индексированные и ассоциативные типы массивов являются одним и тем же типом в PHP, которые могут содержать как целые, так и строковые индексы.

5
ответ дан stillstanding 21 August 2018 в 22:45
поделиться
  • 1
    Преобразование происходит не из-за плохой печати; php определяет, будет ли строка выглядеть числовая, а затем преобразует ее. – Ja͢ck 9 April 2013 в 08:10
  • 2
    Так ты говоришь, что это невозможно? Этот ответ показывает, что есть способ использовать строку, которая выглядит как целое число как ключ в массиве. – Flimm 19 April 2016 в 11:53
  • 3
    ИМХО проблема - это интерпретатор PHP. Невозможно даже представить себе язык, который смешивает строки и целые числа в виде ключей массива. Лучшее решение? Как было предложено Undolog stackoverflow.com/a/15413637/1977778 , лучшим решением является использование конечного пространства ... К сожалению. – sentenza 19 May 2016 в 14:22
  • 4
    @sentenza: Возможно, это , тем более, что PHP позволяет смешивать строки и целые числа в качестве ключей массива: [42 => 'answer', 'snafu' => 'fubar'] – L S 29 May 2016 в 09:34
  • 5
    @LS yep. Я знаю, что PHP позволяет это сделать, но если вы рассматриваете ключи в гипотетической системе типа generic, это не будет соответствовать смешанному типу , который одновременно включает в себя строки и числа. свободный ввод текста , примененный к ключам ассоциативного массива, является просто склонным к ошибкам. – sentenza 31 May 2016 в 08:47

Строки, содержащие действительные целые числа, будут переданы в целочисленный тип. Например. ключ «8» будет фактически сохранен под 8. С другой стороны, «08» не будет выбрано, так как оно не является допустимым десятичным целым.

WRONG

У меня есть функция кастинга, которая обрабатывает последовательную привязку ассоциативного массива,

$array_assoc = cast($arr,'array_assoc');

$array_sequential = cast($arr,'array_sequential');

$obj = cast($arr,'object');

$json = cast($arr,'json');



function cast($var, $type){

    $orig_type = gettype($var);

    if($orig_type == 'string'){

        if($type == 'object'){
            $temp = json_decode($var);
        } else if($type == 'array'){
            $temp = json_decode($var, true);
        }
        if(isset($temp) && json_last_error() == JSON_ERROR_NONE){
            return $temp;
        }
    }
    if(@settype($var, $type)){
        return $var;
    }
    switch( $orig_type ) {

        case 'array' :

            if($type == 'array_assoc'){

                $obj = new stdClass;
                foreach($var as $key => $value){
                    $obj->{$key} = $value;
                }
                return (array) $obj;

            } else if($type == 'array_sequential'){

                return array_values($var);

            } else if($type == 'json'){

                return json_encode($var);
            }
        break;
    }
    return null; // or trigger_error
}
1
ответ дан TarranJones 21 August 2018 в 22:45
поделиться

Мое обходное решение:

$id = 55;
$array = array(
  " $id" => $value
);

Пробел char (preend) является хорошим решением, потому что сохраняйте int-преобразование:

foreach( $array as $key => $value ) {
  echo $key;
}

Вы увидите 55 как int .

8
ответ дан Undolog 21 August 2018 в 22:45
поделиться
  • 1
    Или "0$id" => $value. Также работает предварительная работа с 0. – nawfal 18 November 2015 в 11:00
  • 2
    @nawfal спасибо, я не ожидал найти ответ здесь – Va1iant 13 February 2016 в 19:41
  • 3
    Таким образом, вы говорите, что невозможно использовать цифровую строку типа «123». как ключ в массиве PHP, без преобразования его в целое число? – Flimm 19 April 2016 в 11:46
Другие вопросы по тегам:

Похожие вопросы: