Добавление условного форматирования и пунктуации в набор переменных - PullRequest
1 голос
/ 15 апреля 2009

Мне часто приходится перечислять элементы, разделенные запятыми, пробелами или пунктуацией, классическим примером являются адреса (для адреса это излишне, а для примера!)

echo "L$level, $unit/$num $street, $suburb, $state $postcode, $country.";
//ouput: L2, 1/123 Cool St, Funky Town, ABC 2000, Australia.

Как бы просто это не звучало, есть ли простой способ "условно" добавить пользовательские разделители между переменными, только если переменная существует? Нужно ли проверять, установлена ​​ли каждая переменная? Таким образом, используя вышеизложенное, другой адрес с меньшей детализацией может вывести что-то вроде:

//L, / Cool St, , ABC , .

Немного трудным способом проверки было бы видеть, установлена ​​ли каждая переменная, и отображать пунктуацию.

if($level){ echo "L$level, "; }
if($unit){ echo "$unit"; }
if($unit && $street){ echo "/"; }
if($street){ echo "$street, "; }
if($suburb){ echo "$suburb, "; }
//etc...

Было бы хорошо иметь функцию, которая могла бы автоматически выполнять все операции по зачистке / форматированию и т. Д .:

somefunction("$unit/$num $street, $suburb, $state $postcode, $country.");

Другим примером является простой список CSV. Я хочу вывести x элементов, разделенных запятой:

for($i=0; $i=<5; $i++;){ echo "$i,"; }
//output: 1,2,3,4,5,

Например, в цикле, каков наилучший способ определения последнего элемента массива, или выполняется условие цикла, чтобы в конце списка не было запятой? Один длинный путь, который я прочитал, - это поставить запятую перед элементом, кроме первой записи, например:

$firstItem = true; //first item shouldn't have comma
for($i=0; $i=<5; $i++;){
  if(!$firstItem){ echo ","; }
  echo "$i";
  $firstItem = false;
}

Ответы [ 8 ]

3 голосов
/ 15 апреля 2009

В первом примере вы можете использовать массивы в сочетании с несколькими методами массива, чтобы получить желаемый результат. Например:

echo join(', ', array_filter(array("L$level", join(' ', array_filter(array(join('/', array_filter(array($unit, $num))), $street))), $suburb, join(' ', array_filter(array($state, $postcode))), $country))) . '.';

Этот однострочный текст довольно сложен для чтения, поэтому всегда можно заключить вызов array, array_filter и объединить вызовы в отдельный метод и использовать его:

function merge($delimiter)
{
    $args = func_get_args();
    array_shift($args);
    return join($delimiter, array_filter($args));
}

echo merge(', ', "L$level", merge(' ', merge('/', $unit, $num), $street), $suburb, merge(' ', $state, $postcode), $country) . '.';

Вам нужны вызовы array_filter, чтобы удалить пустые записи, в противном случае разделители все равно будут распечатаны.

Для вашего второго примера, добавьте элементы в массив, затем используйте объединение, чтобы вставить разделитель:

$arr = array();
for($i=0; $i=<5; $i++)
{
    $arr[] = $i;
}
echo(join(',', $arr));
1 голос
/ 15 апреля 2009

хорошо, возьми это! (но не слишком серьезно ^^)

<?php

function bothOrSingle($left, $infix, $right) {
    return $left && $right ? $left . $infix . $right : ($left ? $left : ($right ? $right : null));
}

function leftOrNull($left, $postfix) {
    return $left ? $left . $postfix : null;
}

function rightOrNull($prefix, $right) {
    return $right ? $prefix . $right : null; 
}

function joinargs() {
    $args = func_get_args();
    foreach ($args as $key => $arg) 
        if (!trim($arg)) 
            unset($args[$key]);

    $sep = array_shift($args);
    return join($sep, $args);
}

$level    = 2;
$unit     = 1;
$num      = 123;
$street   = 'Cool St';
$suburb   = 'Funky Town';
$state    = 'ABC';
$postcode = 2000;
$country  = 'Australia';

echo "\n" . '"' . joinargs(', ', rightOrNull('L', $level), bothOrSingle(bothOrSingle($unit, '/', $num), ' ', $street), bothOrSingle($state, ' ', $postcode), bothOrSingle($country, '', '.')) . '"';

// -> "L2, 1/123 Cool St, ABC 2000, Australia."

$level    = '';
$unit     = '';
$num      = '';
$street   = 'Cool St';
$suburb   = '';
$state    = 'ABC';
$postcode = '';
$country  = '';

echo "\n" . '"' . joinargs(
    ', ', 
    leftOrNull(
        joinargs(', ', 
            rightOrNull('L', $level), 
            bothOrSingle(bothOrSingle($unit, '/', $num), ' ', $street), 
            bothOrSingle($state, ' ', $postcode), 
            $country
        ),
        '.'
    )
) . '"';

// -> "Cool St, ABC."


$level    = '';
$unit     = '';
$num      = '';
$street   = '';
$suburb   = '';
$state    = '';
$postcode = '';
$country  = '';

echo "\n" . '"' . joinargs(
    ', ', 
    leftOrNull(
        joinargs(', ', 
            rightOrNull('L', $level), 
            bothOrSingle(bothOrSingle($unit, '/', $num), ' ', $street), 
            bothOrSingle($state, ' ', $postcode), 
            $country
        ),
        '.'
    )
) . '"';

// -> "" (even without the dot!)

?>

да, я знаю - выглядит как блядь.

1 голос
/ 15 апреля 2009

Решение Филиппа, вероятно, лучше всего подходит для работы с массивами (если вам не нужно отфильтровывать пустые значения), но если вы не можете использовать функции массива - например, при работе с результатами запроса, возвращенными из mysqli_fetch_object() - тогда одно решение - это просто выражение if:

$list = '';
$row=mysqli_fetch_object($result);
do {
    $list .= (empty($list) ? $row->col : ", {$row->col}");
} while ($row=mysqli_fetch_object($result));

Или, альтернативно:

do {
    if (isset($list)) {
        $list .= ", {$row->col}";
    } else $list = $row->col;
} while ($row=mysqli_fetch_object($result));

Чтобы построить список и отфильтровать пустые значения, я написал бы пользовательскую функцию:

function makeList() {
    $args = array_filter(func_get_args()); // as per Jon Benedicto's answer
    foreach ($args as $item) {
        if (isset($list)) {
            $list .= ", $item";
        } else {
            $list = $item;
        }
    }
    if (isset($list)) {
        return $list;
    } else return '';
}

Тогда вы можете назвать это так:

$unitnum = implode('/',array_filter(array($unit,$num)));
if ($unitnum || $street) {
    $streetaddress = trim("$unitnum $street");
} else $streetaddress = '';
if ($level) {
    $level = "L$level";
}
echo makeList($level, $streetaddress, $suburb, $state $postcode, $country).'.';
1 голос
/ 15 апреля 2009

Есть простое решение вашей второй проблемы:

for($i=0; $i<=5; $i++)
    $o .= "$i,";
echo chop($o, ',');
1 голос
/ 15 апреля 2009

Пока ответ Филиппа отвечает на ваш вопрос, я хотел дополнить его следующим постом в блоге Eric Lippert . Хотя его обсуждение ведется на языке c #, оно применимо к любому языку программирования.

0 голосов
/ 15 апреля 2009

Просто выньте последнюю запятую, т.е. замените ее ничем.

$string1 = "L$level, $unit/$num $street, $suburb, $state $postcode, $country.";
$string1 = eregi_replace(", \.$", "\.", $string1);
echo $string1;

Это сделает работу.

0 голосов
/ 15 апреля 2009
<?php
    $level  = 'foo';
    $street = 'bar';
    $num    = 'num';
    $unit   = '';

    // #1: unreadable and unelegant, with arrays
    $values   = array();
    $values[] = $level ? 'L' . $level : null;
    // not very readable ...
    $values[] = $unit && $num ? $unit . '/' . $num : ($unit ? $unit : ($num ? $num : null));
    $values[] = $street ? $street : null;

    echo join(',',  $values);


    // #2: or, even more unreadable and unelegant, with string concenation
    echo trim( 
        ($level ? 'L' . $level . ', ' : '') . 
        ($unit && $num ? $unit . '/' . $num . ', ' : ($unit ? $unit . ', ' : ($num ? $num . ', ': '')) .
        ($street ? $street . ', ': '')), ' ,');

    // #3: hey, i didn't even know that worked (roughly the same as #1):
    echo join(', ', array(
        $level ? 'L' . $level : null,
        $unit && $num ? $unit . '/' . $num : ($unit ? $unit : ($num ? $num : null)),
        $street ? $street : null
    ));
?>
0 голосов
/ 15 апреля 2009

Я всегда нахожу, что быстрее и проще использовать методы массива языка. Например, в PHP:

<?php
echo join(',', array('L'.$level, $unit.'/'.$num, 
          $street, $suburb, $state, $postcode, $country));
...