G
G
gibigate2020-06-05 16:42:18
PHP
gibigate, 2020-06-05 16:42:18

How to split an array according to a given criterion?

Hello,

There was a problem, I'm looking for an elegant solution with a minimum of code.

There are arrays (since I work only with keys, I will write only them):

[0,1,2,3,4,5]
[0,1,2,3,6,7,8,9,12,13,14,15]
[94,95]
[0,1,94,95]


So the question is to find neighboring numbers and allocate them into a separate array, as a result I need to get the following data:
[ [start=>0, end=>5] ]
[ [start=>0, end=>3], [start=>6,end=>9], [start=>12,end=>15] ]
[ [start=>94, end=>95] ]
[ [start=>0, end=>1], [start=>94, end=>95] ]


Under the conditions that the array always has adjacent keys (at least two adjacent keys)

I could not write a universal function, I hope for you

Answer the question

In order to leave comments, you need to log in

4 answer(s)
R
Rsa97, 2020-06-05
@Rsa97

function intervals($arr) {
  $start = -1;
  $end = -1;
  $result = [];
  foreach ($arr as $val) {
    if ($start === -1) {
      $start = $val;
      $end = $val;
    } elseif ($val === $end + 1) {
      $end = $val;
    } else {
      $result[] = ['start' => $start, 'end' => $end];
      $start = $val;
      $end = $val;
    }
  }
  if ($start !== -1) {
    $result[] = ['start' => $start, 'end' => $end];
  }
  return $result;
}

print_r(intervals([0,1,2,3,6,7,8,9,12,13,14,15]));

// Array (
//     [0] => Array (
//             [start] => 0
//             [end] => 3
//     )
//     [1] => Array (
//             [start] => 6
//             [end] => 9
//      )
//     [2] => Array (
//             [start] => 12
//             [end] => 15
//      )
// )

A
Anton Anton, 2020-06-05
@Fragster

my version:

function convert($data) {
        $result = [];
        $needle = NIL;

        foreach ($data as $item) {
            if ($item - 1 !== $needle) {
                if ($needle !== NIL) {
                    $obj['end'] = $needle;
                    $result[] = $obj;
                }
                $obj = ['start' => $item];
            }
            $needle = $item;
        }
        $obj['end'] = $item;
        $result[] = $obj;

        return $result;
    }

    print_r(convert([0, 1, 2, 3, 4, 5]));
    print_r(convert([0, 1, 2, 3, 6, 7, 8, 9, 12, 13, 14, 15]));
    print_r(convert([94, 95]));
    print_r(convert([0, 1, 94, 95]));

E
Eugene, 2020-06-05
@Nc_Soft

<?php
$dataset = [
    [0, 1, 2, 3, 4, 5],
    [0, 1, 2, 3, 6, 7, 8, 9, 12, 13, 14, 15],
    [94, 95],
    [0, 1, 94, 95],
];

function arrange($array)
{
    $groups = [];
    $group = null;
    foreach ($array as $index => $current) {
        if ($group === null) {
            $group = [
                'start' => $current,
                'end' => $current
            ];
            continue;
        }
        $group['end'] = $current;
        $next = $index + 1;
        if (array_key_exists($next, $array)) {
            if ($array[$next] - $current !== 1) {
                array_push($groups, $group);
                $group = null;
            }
        }
    }
    if ($group !== null) {
        array_push($groups, $group);
    }
    return $groups;
}

foreach ($dataset as $array) {
    $arrange = arrange($array);
    print_r($arrange);
}

V
Vitaly Artemyev, 2020-06-05
@Vitaly48

<?php

$numbers1 = [-5, 10, 0, 1, 2, 3, 6, 7, 8, 9, 12, 13, 14, 15];
$numbers2 = [10, 0, 1, 2, 3, 6, 7, 8, 9, 12, 13, 14, 15];

function intervals(array $numbers): array
{
    $numbers = array_unique($numbers);
    sort($numbers);

    $length = count($numbers);

    $intervals = [];

    $start = null;
    $end   = null;

    for ($i = 0; $i < $length; $i++) {
        $currentItem = $numbers[$i];
        $nextItem    = $numbers[$i + 1] ?? null;

        if ($currentItem + 1 === $nextItem) {
            if ($start === null) {
                $start = $currentItem;
            }

            $end = $nextItem;
            continue;
        }

        if ($start === null || $end === null) {
            continue;
        }

        $intervals[] = [
            'start' => $start,
            'end'   => $end,
        ];

        $start = $nextItem;
    }

    return $intervals;
}

print_r(intervals($numbers1));
print_r(intervals($numbers2));

PS gibigate check the previous answers on an array whose first digit has no pair

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question