调整列宽的数组以适合Bootstrap网格系统

时间:2015-11-18 18:06:07

标签: php arrays regex twitter-bootstrap closest

我正在努力将系统转换为Bootstrap网格,我遇到的问题是如何将当前宽度从PHP中的数组转换为Bootstrap中最接近/“最适合”?

See phpfiddle demo

我们的想法是将新的Bootstrap列宽度基于旧值,遗憾的是旧数据库有一些我需要适应的奇怪值。以下是旧列宽度和cols数量的字符串的六个示例;

  1. %30,%40,%30,% | 3
  2. %,%,%,% | 4
  3. 180,1070,, | 2
  4. 20,80,, | 2
  5. 75%,25%,20%, | 2
  6. ,,, | 1
  7. PHP代码:

    // example of output from database
    $numberOfColumnsFromDatabase = 3;
    $stringFromDatabase = '%30,%40,%30,%';
    // NOT WORKING as intended:
    // 3 cols with string '%30,%40,%30,%'
    // Working as intended:
    // 2 cols with string '180,1070,,'
    // 4 cols with string '%,%,%,%'
    // 2 cols with string '75%,25%,20%,'
    // 1 cols with string ',,,'
    echo 'Original string: "'.$stringFromDatabase.'"'."\n";
    
    // strip percentage and explode to array
    $stringStripped = str_replace('%','',$stringFromDatabase);
    $columnArrayOld = explode(",", $stringStripped);
    
    // only use the amount of columns from database
    $cols = $numberOfColumnsFromDatabase;
    $arrayShortened = array_slice($columnArrayOld, 0, $cols);
    
    // sum it up
    $fullWidth = array_sum($arrayShortened);
    echo 'Full width = '.$fullWidth."\n";
    
    // valid Bootstrap widths
    $arrayToSearch = array(8.3, 16.6, 25, 33.3, 41.6, 50, 58.3, 66.6, 75, 83.3, 91.6, 100);
    
    // calculate % of full width
    $columnArrayStripped = array();
    $columnArrayNew = array();
    if($fullWidth > 0){
      foreach($arrayShortened as $key => $value){
        if(array_key_exists($key, $arrayShortened)) {
          if ($columnArrayOld[$key] == '') {
            break;
          } else {
            $percentage = round($arrayShortened[$key]*10)/$fullWidth*10;
            $closest = getClosest($percentage,$arrayToSearch);
            array_push($columnArrayStripped,$closest);
            array_push($columnArrayNew,$closest.'%');
          }
        }
      }
    }
    else{
      //generate new equal width Bootstrap layout based on number of columns
      //but only if exploded array does not equal column number
      $columnArrayNew = array();
      if(count($columnArrayStripped) != $cols) {
        // if we cant retrieve widths
        for($i=0;$i<$cols;$i++){
            $percentage = round(intval(1000/$cols))/10;
            array_push($columnArrayStripped, $percentage);
            array_push($columnArrayNew, $percentage.'%');
        }
      }
    }
    
    echo 'New clean string: "'.implode(',',$columnArrayStripped).'"'."\n";
    
    echo 'New percentage string: "'.implode(',',$columnArrayNew).'"'."\n";
    
    function getClosest($search, $arr) {
       $closest = null;
       foreach ($arr as $item) {
          if ($closest === null || abs($search - $closest) > abs($item - $search)) {
             $closest = $item;
          }
       }
       return $closest;
    }    
    

    输出:

    Original string: "%30,%40,%30,%"
    Full width = 100
    New clean string: "33.3,41.6,33.3"
    New percentage string: "33.3%,41.6%,33.3%"
    

    正如您所见,33.3 + 41.6 + 33.3超过100%。我理解为什么结果是这样的,因为它的目标是最接近的,但如何防止这样的问题呢?我的目标是让结果字符串具有有效的引导程序宽度,但总数必须介于99.7和100.3之间。

    (我也用正则表达式标记,但答案就在那里)

1 个答案:

答案 0 :(得分:0)

由于缺乏初步反应(没有答案和很少观点),我最终自己解决了这个问题。但是如果有一个关于如何用正则表达式来解决它的好主意,我会暂时留下没有标记的最佳答案。

这是我的解决方案 phpfiddle demo

更改了代码:

if($fullWidth > 0){
  foreach($arrayShortened as $key => $value){
    if(array_key_exists($key, $arrayShortened)) {
      if ($columnArrayOld[$key] == '') {
        break;
      } else {
        $percentage = round($arrayShortened[$key]*10)/$fullWidth*10;
        $closest = getClosest($percentage,$arrayToSearch);
        array_push($columnArrayStripped,$closest);
        array_push($columnArrayNew,$closest.'%');
      }
    }
  }
  echo 'Array sum: '.array_sum($columnArrayStripped)."\n";
  // if max value in array > 100, reduce max value with 8.3
  if(array_sum($columnArrayStripped) > 100){
    $maxKey = array_search(max($columnArrayStripped),$columnArrayStripped);
    if($maxKey) {
      $columnArrayStripped[$maxKey] -= $arrayToSearch[0];
      $columnArrayNew[$maxKey] = $columnArrayStripped[$maxKey].'%';
    }
  }
}