2010-06-08 5 views
1

날짜 배열로 작업하기 (비즈니스를위한 개업 시간). 나는 가능한 한 가장 간단한 형태로 그들을 응축시키고 싶다.PHP : 유사한 문자열을 하나의 병합 된 배열로 압축

지금까지 내가 무엇을 달성하고자하는 것은 이것이다이 구조

Array 
(
    [Mon] => 12noon-2:45pm, 5:30pm-10:30pm 
    [Tue] => 12noon-2:45pm, 5:30pm-10:30pm 
    [Wed] => 12noon-2:45pm, 5:30pm-10:30pm 
    [Thu] => 12noon-2:45pm, 5:30pm-10:30pm 
    [Fri] => 12noon-2:45pm, 5:30pm-10:30pm 
    [Sat] => 12noon-11pm 
    [Sun] => 12noon-9:30pm 
) 

로 시작 : 나는 재귀 함수를 작성 시도하고이 때문에 출력 관리가

Array 
(
    [Mon-Fri] => 12noon-2:45pm, 5:30pm-10:30pm 
    [Sat] => 12noon-11pm 
    [Sun] => 12noon-9:30pm 
) 

멀리 :

Array 
(
    [Mon-Fri] => 12noon-2:45pm, 5:30pm-10:30pm 
    [Tue-Fri] => 12noon-2:45pm, 5:30pm-10:30pm 
    [Wed-Fri] => 12noon-2:45pm, 5:30pm-10:30pm 
    [Thu-Fri] => 12noon-2:45pm, 5:30pm-10:30pm 
    [Sat] => 12noon-11pm 
    [Sun] => 12noon-9:30pm 
) 

누구나 값을 비교하고 키를 결합하는 간단한 방법을 볼 수 있습니다. 그들은 비슷하니? 내 재귀 함수는 기본적으로 두 개의 중첩 된 foreach() 루프입니다. 매우 우아하지는 않습니다.

감사합니다, 매트

편집 : 나는 없다고 생각

$last_time = array('t' => '', 'd' => ''); // blank array for looping 
$i = 0; 

foreach($final_times as $day=>$time) { 

    if($last_time['t'] != $time) { // it's a new time 

     if($i != 0) { $print_times[] = $day . ' ' . $time; } 
     // only print if it's not the first, otherwise we get two mondays 

    } else { // this day has the same time as last time 

     $end_day = $day; 

     foreach($final_times as $day2=>$time2) { 

      if($time == $time2) { 
       $end_day = $day2; 
      } 

     } 

     $print_times[] = $last_time['d'] . '-' . $end_day . ' ' . $time; 

    } 

$last_time = array('t' => $time, 'd' => $day); 
$i++; 

} 
+0

문제가 잘못 정의되었습니다. 프로그램이 화요일이 월 이후에 오는 것을 알기로되어 있습니까? "Mon-Tue, Fri"는 유효한 세트입니까? 접는 규칙은 정확히 무엇입니까? 거기에서 시작해야하며, 구현이 더 분명해질 것입니다. – Artefacto

+0

지금까지 사용하고있는 기능을 우리에게 보여줄 수 있습니까? – Cetra

+0

흠, 좋은 지적. 지능형 일 필요는 없습니다. 예를 들어 Mon, Tue, Wed, Thu 및 Fri의 값이 모두 같은 경우 첫 번째 및 마지막 키 (월 및 금)를 연결해야합니다. 네 말이 맞지만 "월 - 화, 금"도 유효해야합니다. 나는 그것을 통해 또 다른 생각을 가질 것입니다 ... –

답변

1

: 여기 (입력으로 첫 번째부터) 위의 3 배열을 만들어 지금까지 내 코드입니다 특히 이것에 대한 우아한 해결책. 많은 좋은 간단한 해결책을 찾기 위해 노력하고 array_* 기능을 내장 실험 후, 나는 포기하고이 함께했다 :

$lastStart = $last = $lastDay = null; 
$new = array(); 

foreach ($arr as $day => $times) { 
if ($times != $last) { 
    if ($last != null) { 
    $key = $lastStart == $lastDay ? $lastDay : $lastStart . '-' . $lastDay; 
    $new[$key] = $last; 
    } 
    $lastStart = $day; 
    $last = $times; 
} 
$lastDay = $day; 
} 

$key = $lastStart == $lastDay ? $lastDay : $lastStart . '-' . $lastDay; 
$new[$key] = $last;

당신이 반대가 무리를 유지 그것은 단지 하나 개의 foreach 루프를 사용 의 상태. 인접한 요일을 병합 만합니다 (예 : 수요일이 변경되면 Mon-Tue,Thu-Fri과 같은 것을 얻지 못할 것입니다. 두 개의 개별 항목이 생성됩니다).

+0

당신은 영웅입니다, 고마워요! 나는 이것을 통해 훑어보고, 당신이 언급 한 그 엣지 경우를 맞추기 위해 그것을 수정할 수있는 방법을 찾을 수 있는지 알아볼 것입니다. 도와 줘서 고맙습니다 :) –

1

내가 관계형 데이터베이스로 모델링하여 접근하는 것 :

day  start  end 
1  12:00  14:45 
1  17:30  22:30 
... 

다음의 감소 상당히 쉬운 - 특정 시간 간격이 있습니다 :

가 DISTINCT 시작을 선택, 시간표부터 끝까지 가;

그리고이 특정 일에 발생합니다

시작 BY 시간표 GROUP, 끝에서 일 구분자 ',' BY

시작, 끝, GROUP_CONCAT (일) ORDER

(이것은 MySQL을 사용 그런 다음

12:00 14:45 1,2,3,4,5 
17:30 22:30 1,2,3,4,5 
12:00 23:00 6 
12:00 21:30 7 

을 그것을 해결하기 위해 매우 간단 연속 날짜가 이리저리 범위 : - - 단지 'GROUP_CONCAT'기능은 있지만 방법이 을 줄 것)를 사용할 수없는 경우 동일 일 목록.

C.

대안으로서
+0

감사합니다.이 날짜는 이미 관계형 데이터베이스에서 가져오고 있으며, 위에 게시 된 양식으로 변환해야합니다 (기본적으로 날짜와 그룹을 같은 날 여러 번 함께 조정). . 나는 SQL 측에서 더 많은 것을 할 수 있을지도 모르지만, 지금은 위의 Chris Smith의 해결책이 갈 길이라고 생각합니다. –

1

, 난 array_* 기능을 이용하여 함께 버전 자갈 관리. 그러나 어떤 시점에서 '우아함', '효율성'및 '가독성'이 모두 포장되어 남아 있습니다. 그러나 그것은 내가 다른 대답에서 언급 한 모서리의 경우를 다룬다. 그리고 그것이 기능적인 방식으로 행해졌다는 것을 증명하기위한 좋은 따뜻한 빛과 함께 나를 떠났다 (그러나 동시에 부끄러움의 감각을 ...)

$days = array_keys($arr); 
$dayIndices = array_flip($days); 

var_dump(array_flip(array_map(
    function ($mydays) use($days, $dayIndices) { 
     return array_reduce($mydays, 
      function($l, $r) use($days, $dayIndices) { 
       if ($l == '') { return $r; } 
       if (substr($l, -3) == $days[$dayIndices[$r] - 1]) { 
        return ((strlen($l) > 3 && substr($l, -4, 1) == '-') ? substr($l, 0, -3) : $l) . '-' . $r; 
       } 
       return $l . ',' . $r; 
      }, ''); 
    }, array_map(
     function ($day) use ($arr) { 
      return array_keys($arr, $arr[$day]); 
     }, array_flip($arr) 
    ) 
))); 

는 I이 입력과 테스트 :

 'Mon' => '12noon-2:45pm, 5:30pm-10:30pm', 
'Tue' => '12noon-2:45pm, 5:30pm-10:30pm', 
'Wed' => '12noon-2:45pm, 5:30pm-10:00pm', 
'Thu' => '12noon-2:45pm, 5:30pm-10:30pm', 
'Fri' => '12noon-2:45pm, 5:30pm-10:00pm', 
'Sat' => '12noon-2:45pm, 5:30pm-10:30pm', 
'Sun' => '12noon-9:30pm'

그리고 이것을 얻었다 : 기본적 끝에 array_map는 배의 결합 배열에 입력 변환

 ["Mon-Tue,Thu,Sat"]=> string(29) "12noon-2:45pm, 5:30pm-10:30pm" 
    ["Wed,Fri"]=> string(29) "12noon-2:45pm, 5:30pm-10:00pm" 
    ["Sun"]=> string(13) "12noon-9:30pm"

발생 일의 배열. 큰 코드 블록은 array_reduce을 사용하여 멋지게 서식이 지정된 문자열로 그 요일을 줄이고 $days$dayIndices 배열을 참조하여 요일이 연속되는지 확인합니다.

+0

글쎄, 이제는 나 자신을 해보려 고하지 않아서 기쁘다. 익명의 함수와 array_ * 호출을 모두 알아낼 수있는 기술은 절대로 없다. 고맙습니다! 한 가지 문제는 : '구문 분석 오류 : 구문 오류, 예기치 못한 T_FUNCTION, 예상 ')' '라인 시작에 : 코드는 나에게이 오류 제공 기능 ($ mydays) ($ 일을 사용을, $ dayIndices) { 아이디어가 있으십니까? –

+0

@Matt 코드 전체에 산산조각이 나는 것과 같은 익명 함수는 PHP 5.3.0에서 소개되었습니다. 나는 당신이 이전 버전을 사용하고 있다고 생각한다. 이 방법으로 정말로하고 싶다면, 익명의 함수를 적절한 함수로 가져 와서 클로저 대신 전역 변수를 사용해야합니다. 나는 다른 솔루션을 수정하는 것이 더 쉬울 것이라고 생각한다;) – Chris

관련 문제