Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
ну, во-первых реализация удаления элемента скажем так спорная.Задача была написать нечто где ну уж точно никто не может заподозрить ошибку.
Да, я понимаю, что смешаные типы в массиве это забавно, но надо понимать, что это влечет проблемы и их лучше избегать изначально.Совершенно верно — из нужно избегать изначально. На этапе проектирования языка. В Python — уже первый массив не отсортирован, в Lisp — про него даже нельзя сказать отсортирован он или нет (операции сравниения для чисел и строк разные, если пытаться подсунуть «чужеродный» объект — просто вылетит исключение).
Задача была написать нечто где ну уж точно никто не может заподозрить ошибку.
a[i]!=e
вот это условие явно и недвусмысленно на это намекает. В javascript и пхп сравнение всегда стоит производить оператором ===. Исключение из этого правила для js – это сравнение на «неопределенность», тогда следует писать != null, да и то из исключительно практических соображений: некоторые авторы сторонних библиотек пихают null вместо undefined в свойства объектов и передают undefined вместо null в качестве аргументов функции (обычно в функциях с сигнатурой (err, result)).Для сортировки в обоих случаях не применяется обычные операторы сравнения. Просто там некоторые элементы после «сортировки» будут идти не по порядку (в смысле могут быть случаи когда a[i]<a[i+1]>a[i+2] в «отсортированном» массиве).
array("5", 6, 7, "13")
, где тут случай «a[i]<a[i+1]>a[i+2]»?"5" < 6 == true
6 < 7 == true
7 < "13" == true
array(7, "13", "5", 6)
является отсортированным? И какой функцией вы его сортировали?<?php
function remove_element(/* array */ $a, /* element */ $e) {
$b = array();
foreach($a as $m) {
if ($m != $e) array_push($b, $m);
}
return $b;
}
function is_sorted1(/* array */ $a) {
for($i = 0; $i < count($a)-1; $i++) {
if ( $a[$i] > $a[$i+1]) return 0;
}
return 1;
}
function is_sorted2(/* array */ $a) {
$j = 0;
for($i = 0; $i < count($a)-1; $i++) {
if ( $a[$i] < $a[$i+1]) $j++;
}
return $j == count($a)-1 ? 1 : 0;
}
$before = array(7, "13", "5", 6);
$after = remove_element($before, "13");
var_dump($before);
print(is_sorted1($before));
print(is_sorted2($before));
print("\n");
var_dump($after);
print(is_sorted1($after));
print(is_sorted2($after));
?>
Для сортировки в обоих случаях не применяется обычные операторы сравнения.
$before = array(7, "13", "5", 6);
7 < "13" // 7 как число меньше, чем строка "13", приведённая к числу
"13" < "5" //"13" как строка меньше, чем "5" как строка (типа, лексикографически)
Но, 7 > "5" // 7 как число больше, чем строка "5", приведённая к числу
Так как оотношение нетранзитивное, почему множество, на котором оно определено, называется упорядоченным?А как вы ещё назовете множество с операциями больше и меньше?
А как вы ещё назовете множество с операциями больше и меньше?
Хочется также отметить, что языки программирования с динамической типизацией накладывают бОльшую ответственность на разработчика, так как необходимо следить за тем, чтобы не оказаться в ситуации, которую иллюстрирует Ваш пример.Почему тогда подобных проблем нет в Python'е или в Lisp'е? Это — не языки с динамической типизацией уже?
Я все же думаю, что эти правила справедливы только для однородных элементов.Это подход Lisp'а. Грамотный подход IMO.
В случае разнородных элементов к ним применяются разные правила сравнения, в зависимости от типа.
Кроме того, разве правила сравнения строки и числа однозначны? Где-нибудь сказано, что число обязательно нужно приводить к строке и сравнивать как строки? Думаю, это все же зависит от языка.И да и нет. На эту тему есть два подхода, которые можно назвать разумными:
Ну, и еще: как быть с тем, что в Вашем примере (7, «13», «5», 6) соотношения выполняются только для непосредственных соседей, но не дальше? И, как мне кажется, разные методы сортировки входных данных дали бы разные результаты, хотя по логике сортировка массива должна бы быть инвариантна к алгоритму.Это прямое следствие того, что авторы языка непонятно чем думали, когда его разрабатывали.
Много-много лет js-программисты легко и непринуждённо пользуют не-транзитивный ==, без взрывовОй ли? Сколько дыр в безопасности эта помощь проделала? Это ли не «взрывы»? Потом ситуация с == не так остра: есть нормальный оператор ===, который, в общем-то, и нужно использовать.
Столкновение разных типов в js — это жизнь, примитивные значения корреспондируют с соответствующими объектами, из DOM-a/BOM-a разные типы лезут и т.д. и т.п., всё это на лету, и язык даёт возможность не заморачиваться с конвертацией и делает это прозрачно.Ну если вас не волнует работоспособность ваших творений — то да, можно не заморачиваться. Если волнует — заморачиваться таки приходится.
arr = [7, "13", "5", 6]; arr.sort(function(a, b) { return a - b; });
Соответственно, я получу массив [«5», 6, 7, «13»] — массив, отсортированный по моим правилам (а именно ai < aj, j ⊆ {x | i+1 < x ≤ n}).А давайте не будем выдавать желаемое за действительное? В вашем «какбы-типа отсортированном массиве» первый элемент меньше последнего и, соответственно, согласно вашим правилам массив не отсортирован. Более того: он вообще не может быть отсортирнован согласно вашим правилам. В принципе.
Вы же придумали (или просто не задумывались о том, что оно есть) свое правило, которое является достаточно вычурным, а в своем методе удаления элемента это правило не учитываете.А вас не удивляет функция sort, которая нифига не сортирует и в приниципе не может сортировать?
Ну вот в том то и дело, что сортирует, но по другим правилам. Эти правила я причем определил сам, передав функцию их описывающую параметром метода sort, как вы, наверное, заметили.Я это заметил — но это ничего не изменило. Вы пишете что вы называете массив отсортированным если «ai < aj, j ⊆ {x | i+1 < x ≤ n}». Так вот у вас это неверно если i равно нулю, а j равно трём.
То, что вы утверждаете, что операторы < и > в Яваскрипте и ПХП не являются отношениями порядка — абсолютно верно. И если уж подходить к вопросу с позиции отношения порядка, то как раз в вашем примере массив не является отсортированным, т.к. 7 < '13', но больше 6.И в вашем и в моём случае соседние элементы идут в «правильном» порядке, и в вашем и в моём случае массив в целом — не отсортирован. Более того если бы взяли другой массив (скажем [«13», «8», «90»]), то ваша функция его бы сделала из сортированного — несортированным.
Было бы кстати очень узнать источник тех двух свойств отсортированных массивов, о которых вы говорите в своем комментарии чуть выше.Ну вы и сами его знаете — это верно для любого отсортированного массива, если операция сравнения такие является отношением порядка.
Я это заметил — но это ничего не изменило. Вы пишете что вы называете массив отсортированным если «ai < aj, j ⊆ {x | i+1 < x ≤ n}». Так вот у вас это неверно если i равно нулю, а j равно трём.
Мне кажется не стоит хаять языки программирования. Они даны — играйте по их правилам.Я и играю. Получаю маразм. Это вы «меняете правила игры» задавая свою функцию сортировки. Если потом проверить отсортированность массива по «правилам игры языка» — он окажется не отсортированным.
Я и играю. Получаю маразм.
Я и играю. Получаю маразм. Это вы «меняете правила игры» задавая свою функцию сортировки. Если потом проверить отсортированность массива по «правилам игры языка» — он окажется не отсортированным.
Не могли бы вы описать реальную задачу, решая которую вы столкнулись с этой «проблемой»? Задачу, в которой вам необходимо сортировать множество из разнородных элементов.Да легко: у меня есть набор объектов из базы, я добавляю туда парочку своих. В базе ID'шники хранятся как числа, вновь созданные объекты имеют числовые ID'шники (по недосмотру или специально — чтобы не путались с объектами вытащенными из базы). Lisp мне скажет «ты что — придурок?» и я программу поправлю. Python молча проглотит всё и всё будет работать. В JavaScript/PHP всё будет работат у разработчика, но рано или поздно «ляжет» у заказчика. В реальной жизни ID'шники были составными (то есть простой возможности использовать ассоциативные массивы не хватало).
Вообще-то определение «упорядоченный» не указывает, каким конкретно образом множество упорядочивается, главное, чтобы это было отношение порядка.Час от часу не легче. То есть в PHP у нас вызов функции sort() не создают отсортированный массив? Это — новаторский подход, конечно…
В базе ID'шники хранятся как числа, вновь созданные объекты имеют числовые ID'шники
Час от часу не легче. То есть в PHP у нас вызов функции sort() не создают отсортированный массив? Это — новаторский подход, конечно…
array("11", "a", 2, 3)
не является упорядоченным с математической точки зрения. Укажите, где я не прав.Должно быть, вы имели ввиду «вновь созданные объекты имеют строковые ID'шники»?Да, конечно.
Не знаю, как вас, но вот лично меня несколько смущает, что одни и те же объекты хранятся в одном множестве, имея при этом разный тип (это я про ID'шники).А почему нет? Если в базе у нас объекты одного типа, а «фиктивные» объекты имеют другой тип, то это простой способ добиться того, чтобы они никогда не совпали (они, впрочем, в PHP могут совпасть в смысле ==, но не в смысле ====). В Python этот же подход будет отлично работать без каких-либо проблем, в Lisp'е мне придётся определить свою функцию. В PHP я тоже могу определить свою функцию, но вот беда: если я этого не сделаю, то никаких ошибок отдиагностировано не будет — программа просто не заработает.
Не знаю, в чем заключается новаторский подход.Ась? Не знаете или притворяетесь?
Значит массив array(«11», «a», 2, 3) не является упорядоченным с математической точки зрения.С точки зрения математики это — не упорядоченный массив. А вот с точки зрения PHP — вполне себе упорядочнный:
$arr=array("11", "a", 2, 3);
sort($arr);
var_dump($arr);
Если в базе у нас объекты одного типа, а «фиктивные» объекты имеют другой тип
С точки зрения математики это — не упорядоченный массив. А вот с точки зрения PHP — вполне себе упорядочнный.
Где отношения порядка нетранзитивны, а сортировка имеет другой смысл нежели в математике.
Скажите, а что если упорядочивать не просто множество из строк и чисел, а вообще из произвольных объектов, то там отношения "<" и ">" будут отношениями порядка? Я имею ввиду именно встроенные, а не перегруженные.Если язык вменяем — то да. Скажем Python это гарантирует. Либо, как вариант, такой возможности в языке вообще нет — ну на нет и суда нет.
а сортировать в одной последовательности числа и строки произвольно изменяя операцию сравнения чисел на операцию сравнения строк, это как сортировать купюры (разных образцов) и монеты, то по весу, то по номиналу.
var_dump('asd' < 1); // true
var_dump(1 < '2a'); // true
var_dump('asd' < '2a'); // false
Выходит автор просто не читал мануала к PHPЯ как раз прочитал описания мануала к PHP — и мне стало дурно.
написано, что это Comparison Operators, причем с неочевидными правилами сравнения и приведения типов для разных типов операндовДа-да-да. Вот только беда: там не написано какому идиоту пришло в голову придумать такие правила. Как их использовать-то?
alert( [(2 + '3'), (2 + 3), (3 + '2')] ); //-> 23,5,32
Будьте осторожны при сортировке массивов, содержащих элементы разных типов, так как в этом случае результат работы функции sort() может быть непредсказуемым.
function remove_element(/* array */ $a, /* element */ $e) { $b=array(); foreach($a as $m) { if ($m!=$e) array_push($b, $m); } return $b; } $before=array("11", "a", 2, 3); $after=remove_element($before, "a");
$before = array(0 => "11", 1 => "a", 2 => 2, 3 => 3);
$after = array(0 => "11", 1 => 2, 2 => 3);
a = [1, "5", 30, "25", 100, 4576, "2534", 11234, "10244", 21, 24, 30, "2534", 34434, "234435"]
К вопросу о языках программирования…