/** * Summarize numbers to ranges by keys ['vinicola'=>'Torres', 'variaety'=>'merlot', 'vintage'=>'2010-2015, 2018'] * * * @precondition $data orderd by ['key_1', 'key_2', ... 'int'] * @param array $keys ['key_1', 'key_2', ..] * @param string $rangeKey key to an integer to summarize by range * @param array $data [['key_1'=>'a', 'key_2', 'int'=>2014], ['key_1'=>'a', 'key_2', 'int'=>2015],...] * @param bool $md5Key true use md5 for hashkey, uses key_1\tkey_2\t... * @return array ['key_1\tkey_2\t'=>['key_1'=>'Winery 1' 'key_2' => 'merlot' => 'vintage'=>'2010-2014, 2015-2016, 2018'], ...] */ function iaNumbers2Ranges($keys, $rangeKey, $data, $md5Key=false) { $joinWith = '-'; // I think it's better to put n-dash symbol (U+2013) without spaces on sides. $separateBy = ', '; $changed = 0; $prevHash = []; $sumarized = []; $keyExtractor = array_flip($keys); foreach($data as $d) { $part = array_intersect_key($d, $keyExtractor); $hash = implode("\t", array_intersect_key($d, $part) ); if($md5Key) { $hash = md5($hash); } if(!isset($sumarized[$hash])) { $sumarized[$hash] = $part; } if(!isset($d[$rangeKey])) { if(!isset($sumarized[$hash][$rangeKey])) { $sumarized[$hash][$rangeKey] = ''; } continue; } $value = $d[$rangeKey]; if(!isset($prevHash[$hash])) { $sumarized[$hash][$rangeKey] = $value; $prevHash[$hash] = is_numeric($value) ? (int)$value : $value; continue; } $prevTop = $prevHash[$hash]; if(!is_numeric($value) || !is_numeric($prevTop)) { $sumarized[$hash][$rangeKey] .= $separateBy.$value; } elseif( $prevTop + 1 == $value) { $sumarized[$hash][$rangeKey] = str_replace($joinWith.$prevTop, $joinWith.$value, $sumarized[$hash][$rangeKey], $changed); if($changed === 0) { $sumarized[$hash][$rangeKey] .= $joinWith.$value; } } else { $sumarized[$hash][$rangeKey] .= $separateBy.$value; } $prevHash[$hash] = is_numeric($value) ? (int)$value : $value; } return $sumarized; }