hypertensy
hypertensy

Reputation: 235

How correctly to process an arrays?

There are two arrays:

$arr1 = ['word', 'tech', 'care', 'kek', 'lol', 'wild', 'regex'];
$arr2 = ['ord', 'ek', 'ol', 'ld', 'gex', 'ss'];

The number of elements in the second array is less than or equal to the first array.

Sort out the first array and the second array, if the elements of the second array are contained at the end of the elements of the first array, sort the array in this form:

Array
(
    [0] => w_ord
    [1] => tech
    [2] => care
    [3] => k_ek
    [4] => l_ol
    [5] => wi_ld
    [6] => re_gex
)

Important: the elements of the second array are never repeated, and can go in any order. If in the second element there is no end of the element of the first array, then set the value of the element of the first array.

I do this:

foreach($arr2 as $val) {
    $strrepl[$val] = "_".$val;
}

foreach($arr1 as $key => $val) {
    $arr3[$key] = str_replace(array_keys($strrepl), $strrepl, $val);
}

print_r($arr3);

But I'm not sure that this is the right approach, what will you advise?

Upvotes: 8

Views: 236

Answers (5)

sevavietl
sevavietl

Reputation: 3812

Another approach can be to create complex regex beforehand (using implode and preg_quote for safety) and use it for replacement inside array_map callback:

$arr1 = ['word', 'tech', 'care', 'kek', 'lol', 'wild', 'regex'];
$arr2 = ['ord', 'ek', 'ol', 'ld', 'gex', 'ss'];

$regex = '/(' . implode('|', array_map('preg_quote', $arr2)) . ')$/';

$result = array_map(function ($word) use ($regex) {
    return preg_replace($regex, '_$1', $word);
}, $arr1);

Here is the demo.

Upvotes: 3

Elementary
Elementary

Reputation: 1453

You can try this.I think it is easy to understand :

$arr1=['word','tech','care','kek','lol','wild','regex'];
$arr2=['ord','ek','ol','ld','gex','ss'];

foreach($arr1 as $key=>$fullword){
    foreach($arr2 as $substr){
        $arr1[$key]=preg_replace('/' . $substr . '$/', '_' . $substr, $fullword,-1,$count);
        if($count) break;
    }
}

i go throught the array of fullword and as soon as i find a match i stop the search.

Upvotes: 3

Andreas
Andreas

Reputation: 23958

You can use preg_grep which is regex on arrays.
This code will also make sure it can output more than one matching word from $arr1.

$arr1 = ['word', 'chord', 'tech', 'care', 'kek', 'lol', 'wild', 'regex'];
$arr2 = ['ord', 'ek', 'ol', 'ld', 'gex', 'ss'];

$keys=[];
foreach($arr2 as $val){
    $matches = preg_grep("/.+" . preg_quote($val) . "/", $arr1);
    $keys = array_merge($keys, array_keys($matches)); // save keys of matched words
    foreach($matches as $key => $m) $new[$val][] = str_replace($val, "_$val", $arr1[$key]);
}
$new['unmatched'] = array_diff_key($arr1, array_flip($keys)); // add unmatched words
var_dump($new);

Output:

array(6) {
  ["ord"]=>
  array(2) {
    [0]=>
    string(5) "w_ord"
    [1]=>
    string(6) "ch_ord"
  }
  ["ek"]=>
  array(1) {
    [0]=>
    string(4) "k_ek"
  }
  ["ol"]=>
  array(1) {
    [0]=>
    string(4) "l_ol"
  }
  ["ld"]=>
  array(1) {
    [0]=>
    string(5) "wi_ld"
  }
  ["gex"]=>
  array(1) {
    [0]=>
    string(6) "re_gex"
  }
  ["unmatched"]=>
  array(2) {
    [2]=>
    string(4) "tech"
    [3]=>
    string(4) "care"
  }
}

https://3v4l.org/gfUea

Upvotes: 4

Rafael
Rafael

Reputation: 1535

Surprisingly, this one was quite fun to execute. Since you went very specific on end of the element, I decided to use RegEx for that.

Here is my approach:

$arr1 = ['word', 'tech', 'care', 'kek', 'lol', 'wild', 'regex'];
$arr2 = ['ord', 'ek', 'ol', 'ld', 'gex', 'ss'];

foreach ($arr2 as $find) {
   foreach ($arr1 as $key => $element) {
        $arr1[$key] = preg_replace('/' . $find . '$/', '_' . $find, $element);
    }
}

For every element of the second array (since they are not repeated), I go through every element of the first array and check if the value can be found at the end of the element of the second array using the $ anchor from RegEx which forces it to look it from the end of the string.

This way the $arr1 will have exactly what you expect.

[Edit] Following the scape suggestion from @aefxx and improving variable names.

Upvotes: 5

aefxx
aefxx

Reputation: 25249

Hmm, let's see ... purely functional 'cause you know :D

function ends($str) {
  return function($suffix) use($str) {
    return mb_strlen($str) >= mb_strlen($suffix)
      && mb_substr($str, mb_strlen($suffix) * -1) === $suffix;
  };
}

$result = array_map(function($item) use($arr2) {
  $filter = ends($item);
  $suffixes = array_filter($arr2, $filter);

  if (empty($suffixes)) {
    return $item;
  }
  // This only cares about the very first match, but
  // is easily adaptable to handle all of them
  $suffix = reset($suffixes);

  return mb_substr($item, 0, mb_strlen($suffix) * -1) . "_{$suffix}";
}, $arr1);

Upvotes: 7

Related Questions