Вы можете сделать это с помощью usort
. Аргумент $cmp_function
может быть:
function my_sorter($a, $b) {
$c = strcmp($a['state'], $b['state']);
if($c != 0) {
return $c;
}
$c = strcmp($a['event_type'], $b['event_type']);
if($c != 0) {
return $c;
}
return strcmp($a['date_start'], $b['date_start']);
}
Для произвольного количества полей в PHP 5.3 вы можете использовать замыкания для создания функции сравнения:
function make_cmp($fields, $fieldcmp='strcmp') {
return function ($a, $b) use (&$fields) {
foreach ($fields as $field) {
$diff = $fieldcmp($a[$field], $b[$field]);
if($diff != 0) {
return $diff;
}
}
return 0;
}
}
usort($arr, make_cmp(array('state', 'event_type', 'date_start')))
Для произвольное количество полей разных типов в PHP 5.3:
function make_cmp($fields, $dfltcmp='strcmp') {
# assign array in case $fields has no elements
$fieldcmps = array();
# assign a comparison function to fields that aren't given one
foreach ($fields as $field => $cmp) {
if (is_int($field) && ! is_callable($cmp)) {
$field = $cmp;
$cmp = $dfltcmp;
}
$fieldcmps[$field] = $cmp;
}
return function ($a, $b) use (&$fieldcmps) {
foreach ($fieldcmps as $field => $cmp) {
$diff = call_user_func($cmp, $a[$field], $b[$field]);
if($diff != 0) {
return $diff;
}
}
return 0;
}
}
function numcmp($a, $b) {
return $a - $b;
}
function datecmp($a, $b) {
return strtotime($a) - strtotime($b);
}
/**
* Higher priority come first; a priority of 2 comes before 1.
*/
function make_evt_prio_cmp($priorities, $default_priority) {
return function($a, $b) use (&$priorities) {
if (isset($priorities[$a])) {
$prio_a = $priorities[$a];
} else {
$prio_a = $default_priority;
}
if (isset($priorities[$b])) {
$prio_b = $priorities[$b];
} else {
$prio_b = $default_priority;
}
return $prio_b - $prio_a;
};
}
$event_priority_cmp = make_evt_prio_cmp(
array('meeting' => 5, 'party' => 10, 'concert' => 7),
0);
usort($arr, make_cmp(array('state', 'event' => $event_priority_cmp, 'date_start' => 'datecmp', 'id' => 'numcmp')))
Лично мне очень редко приходится выполнять потоковую передачу в один и тот же строковый поток и из него.
Обычно я хочу либо инициализировать поток из строки, а затем проанализировать его; или передавать вещи в строковый поток, а затем извлекать результат и сохранять его.
Если вы транслируете в один поток и из одного потока, вы должны быть очень осторожны с состоянием потока и позициями потока.
Использование «просто» istringstream
или ostringstream
лучше выражает ваше намерение и дает вам некоторую проверку против глупых ошибок, таких как случайное использование <<
vs ] >>
.
Там могло быть некоторое улучшение производительности, но я бы не стал обращать внимание на это в первую очередь.
Нет ничего плохого в том, что вы написали. Если вы обнаружите, что он не работает достаточно хорошо, вы можете профилировать другие подходы, в противном случае придерживайтесь того, что является наиболее ясным. Лично я бы просто набрал:
std::string stHehe( "Hello stackoverflow.com!" );
A stringstream
несколько больше, и может иметь несколько меньшую производительность - множественное наследование может потребовать корректировки указателя vtable. Основное различие заключается (по крайней мере, в теории) в лучшем выражении намерений и предотвращении случайного использования >>
там, где предполагалось <<
(или наоборот). В то же время, разница достаточно мала, поэтому, особенно для быстрых кусков демонстрационного кода и тому подобного, я ленюсь и просто использую stringstream
. Я не могу вспомнить, когда я в последний раз случайно использовал <<
, когда хотел >>
, так что для меня эта часть безопасности кажется в основном теоретической (тем более, что если вы сделаете такую ошибку, она почти всегда будет действительно очевидна почти сразу).
Нет ничего плохого в том, чтобы просто использовать строку, если это позволяет достичь того, чего вы хотите. Если вы просто собираете строки вместе, это просто и работает отлично. Если же вы хотите форматировать другие типы данных, stringstream
будет поддерживать это, а строка, в основном, нет.
istringstream - для ввода, ostringstream - для вывода. stringstream - ввод и вывод. Вы можете использовать stringstream практически везде. Однако, если вы передадите свой объект другому пользователю, и он использует оператор >>, тогда как вы ждали объект только для записи, вы не будете счастливы ;-)
PS: ничего плохого в этом нет, просто проблемы с производительностью.
Предположительно, если для вашей операции подходит только вставка или только извлечение, вы можете использовать одну из версий с префиксом 'i' или 'o', чтобы исключить нежелательную операцию.
Если это не важно, то можно использовать версию i/o.
Конкатенация строк, которую вы показываете, вполне допустима. Хотя конкатенация с помощью строкового потока возможна, это не самая полезная особенность строковых потоков, которая заключается в возможности вставлять и извлекать POD и абстрактные типы данных.
Отвечу на ваш третий вопрос: Нет, это совершенно разумно. Преимущество использования потоков заключается в том, что вы можете вводить любое значение, для которого определен оператор <<
, в то время как вы можете добавлять только строки (C ++ или C) в std :: string
.
Зачем открывать файл для чтения / записи, если, например, вам нужно только читать из него?
Что, если несколько процессов должны читать из одного и того же файла?
В большинстве случаев вам не понадобятся и ввод, и вывод в одном строковом потоке, поэтому использование std :: ostringstream
и std :: istringstream
явно указывает на ваше намерение чистый. Это также предотвращает случайный ввод неправильного оператора ( <<
vs >>
).
Если вам нужно выполнить обе операции в одном потоке, вы, очевидно, воспользуетесь версией общего назначения.
Проблемы с производительностью будут наименьшей из ваших проблем, ясность - главное преимущество.
Наконец, нет ничего плохого в использовании добавления строк, поскольку вам нужно создавать чистые строки. Вы просто не можете использовать это для объединения чисел, как в таких языках, как Perl.