2009-04-15 5 views
1

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

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. Я хочу выходные элементы х, разделенных запятая:

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; 
} 

ответ

0

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

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

Не решите проблему, если вы не проверите на isset или empty перед добавлением каждого элемента. – Tobias

+0

как я (см. Ниже, № 3). unfortunatley, что делает его намного менее изящным. – stefs

1

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

1

Там простое решение вашей второй задачи:

for($i=0; $i<=5; $i++) 
    $o .= "$i,"; 
echo chop($o, ','); 
1

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

$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).'.'; 
+0

Я считаю, что это приближается, адрес улицы также может использовать функцию makeList, поскольку она все равно вернет пространство и/если одна из трех переменных пустая ... следовательно, основная часть проблемы ... –

+0

Вы также хорошо разбираетесь в массивах, чаще всего данные поступают из MySQL, что означает, что есть дополнительный шаг для создания массива или массивов. –

+0

Иногда с такими элементами, как адрес улицы и уровень, наиболее простым решением является простое использование операторов if для их пользовательского форматирования. Было бы нецелесообразно создавать настраиваемую функцию для обработки одноразовых задач форматирования. – Calvin

3

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

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_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)); 
+0

Если мне когда-либо приходилось поддерживать ваш код, я бы очень хотел увидеть что-то вроде «трудного» метода в вопросе. Это однолинейное решение - углылый. –

+0

+1. Я до сих пор не слышал о array_filter(). – Calvin

+0

Я согласен, что однострочный шрифт может быть трудночитаемым, поэтому я добавил еще один пример, который реорганизует массив, array_filter и объединяет вызовы в вспомогательный метод. –

0
<?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

Хотя эти решения работают, похоже, какой-то прочный код для кажущегося простого выхода ... для более сложной компоновки было бы даже более увлекательно обдумывать эти варианты ... спасибо за вклад! –

+0

Имхо №3 не так уж плохо. в моем примере это выглядит хуже, чем есть, потому что я рассмотрел каждый вариант для комбинации единиц/номеров. и он отображается правильно, если есть пустые значения (нет «foo ,, bar»). Некоторым людям не нравится (иногда плохо) читаемость? Конструкция, жесткая. – stefs

0

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

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

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

+0

Я так не думаю, потому что если $ suburb пуст, в середине будут двойные запятые (не приятно). – stefs

1

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

<?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!) 

?> 

Да, я знаю - выглядит немного как мозговой ублюдок.

+0

geez, и я пытался упростить «трудный» способ сделать это :) Это похоже на завтрак для собак, но элементы полезны. Как только выход будет решен, joinargs могут иметь функции для каждого вывода, поэтому для адресов просто вызовите: doaddress ($ level, $ unit, $ num, $ street, $ state, $ postcode, $ country); –

Смежные вопросы