Возьмем заданные массивы:
// Original
array:14 [
0 => "hello"
1 => "i"
2 => "like"
3 => "cats"
4 => "they're"
5 => "cute"
6 => "and"
7 => "cuddly"
8 => "you"
9 => "know"
10 => "well"
11 => "i"
12 => "love"
13 => "cats"
]
// Sliced
array:6 [
0 => "like"
1 => "cats"
2 => "they're"
3 => "cute"
4 => "and"
5 => "cuddly"
]
Я хочу проверить массив original
на предмет моих значений sliced
и получить их исходные ключи. Это должно происходить только при совпадении последовательных значений.
В конечном итоге что-то вроде:
return array_keys_from_consec_values($original, $sliced);
// Result
array:14 [
0 => 2
1 => 3
2 => 4
3 => 5
4 => 6
5 => 7
]
sliced
не является результатом использования array_slice()
в массиве original
. В противном случае я бы использовал эту функцию и использовал бы параметр сохранения ключей.
Хочу избежать двусмысленности. Например, простой array_search
для cats
вернет ключ 3
, но 13
также существует. Что может сбить функцию.
В случае, если какое-либо из значений sliced
не существует в original
(по порядку), должен быть возвращен пустой массив. Пример отказавшего массива sliced
:
// Sliced
array:6 [
0 => "like"
1 => "cats"
2 => "they're"
3 => "cut3"
4 => "and"
5 => "cuddly"
]
Любые рекомендации, учли скорость ...
Я не понимаю, чего вы ожидаете от результата?
оба являются массивом или строкой?
что ты уже испробовал?
Что вы имеете в виду под происходит последовательное совпадение значений? ОП вам нужно быть более отзывчивым ...
если все значения в sliced
существуют в original
и в порядке (рядом друг с другом и по возрастанию), то верните ключи из original
на основе совпадающих значений ... проверьте первую часть моего вопроса ...
Я до сих пор не совсем понял, проверьте свой ответ (и обновите свой вопрос тем, что вы пробовали до сих пор)
"Нарезанный" массив исходит из array_slice()
? Если это так, у функции есть возможность сохранить клавиши во время нарезки.
Это не так, смотрите обновленные.
Вы сдались ???
Нет, я ответил на свой вопрос. См. Принятый ответ.
Насколько я понял, вы хотите получить индекс из массива $original
на основе значений в $slice
, вы можете использовать функции array_flip()
и array_unique()
:
function array_keys_from_consec_values($original, $slice){
// Get rid of duplicates and flip the keys with the values
$index = array_unique($original);
$index = array_flip($index);
$result = [];
// Loop through the slice
foreach($slice as $key => $value){
// Check if the value exists in the indexed array
if (!isset($index[$value])){
// Return an empty array
return array();
}
// And get the key from the flipped array
$result[$key] = $index[$value];
}
return $result;
}
var_dump(array_keys_from_consec_values($original, $slice));
Это даст:
array (size=6)
0 => int 2
1 => int 3
2 => int 4
3 => int 5
4 => int 6
5 => int 7
Да, это почти готово, но моя самая большая проблема - это неясности. На самом деле нам нужен первый появляющийся ключ cats
(2
). Я полагаю, тогда мы могли бы пойти дальше и отключить его ... так что мы получим 13
при следующем звонке.
Думаю, мы на правильном пути, я приму это, потому что это хорошее усилие, и завтра у меня будет еще одна игра.
Это работает с данными вашего примера и может быть достаточно хорошим:
$r = array_keys(array_unique(array_intersect($o, $s)));
Если нет, поскольку у вас есть срез:
if (($k = array_search($s[0], $o)) === false ||
array_values($r = array_slice($o, $k, count($s), true)) != $s) {
$r = [];
}
Для вашего примера это дает:
Array
(
[2] => like
[3] => cats
[4] => they're
[5] => cute
[6] => and
[7] => cuddly
)
Я вижу после того, что вы хотите получить ключи:
$r = array_values(array_flip($r));
Если фрагмент является фактическим array_slice
из оригинала, то передайте true
в качестве четвертого параметра, чтобы сохранить ключи.
Хорошо, я сыграю. Срез массива, если он не используется в исходном массиве, поэтому нельзя использовать функцию и ее параметр сохранения ключей.
Люди, приложившие усилия, я признаю, что просьбу было немного сложно объяснить - поэтому я не получил именно то, что искал. Я понял, что мне нужен был array_search
, который возвращает несколько ключей при последовательном нахождении игл. Я пошел дальше и сам сделал функцию:
/**
* Search for consecutive needles in haystack and return the corresponding keys.
*
* @param array $needles => Array values.
* @param array $haystack => Array to search.
* @param int $searchDirection => [0] (forwards) | [1] (backwards).
* @return array
*/
function array_search_all_consec(array $needles, array $haystack, $searchDirection = 0)
{
$needlesInScope = array_values($needles); // Keys not relevant, reset them.
$haystackInScope = $haystack;
if (in_array(reset($needlesInScope), $keys = array_keys($haystackInScope))) {
$needlesLength = count($needlesInScope);
foreach (($searchDirection == 0 ? $keys : array_reverse($keys)) as $offset) {
$length = $offset + $needlesLength;
$sliced = array_slice($haystackInScope, $offset, $length);
if (empty(array_diff_assoc($needlesInScope, $sliced))) {
return range($offset, $length - 1);
}
}
}
return [];
}
$o = [
0 => "hello",
1 => "i",
2 => "like",
3 => "cats",
4 => "they",
5 => "cute",
6 => "and",
7 => "cuddly",
8 => "you",
9 => "know",
10 => "well",
11 => "i",
12 => "love",
13 => "cats",
];
$s = [
"i",
"love",
"cats",
];
return array_search_all_consec($s, $o);
// Result
array(3) {
[0] =>
int(11)
[1] =>
int(12)
[2] =>
int(13)
}
$s = [
"i",
"like",
"cats",
];
return array_search_all_consec($s, $o);
// Result
array(3) {
[0] =>
int(1)
[1] =>
int(2)
[2] =>
int(3)
}
$s = [
"i",
"lov3",
"cats",
];
return array_search_all_consec($s, $o);
// Result
array(0) {
}
$s = [
"cats",
"i",
"love",
];
return array_search_all_consec($s, $o);
// Result
array(0) {
}
$s = [
"i",
"love",
"cats",
"blah",
];
return array_search_all_consec($s, $o);
// Result
array(0) {
}
вы имеете в виду, что нужно только существовать в срезе?