Check if array contains elements having elements of another array - php

$find=array('or','and','not');
$text=array('jasvjasvor','asmasnand','tekjbdkcjbdsnot');
I have to check if text array contains any of the elements find has. I'm able to do this for single text but don't know how to do it for all texts
$counter=0;
foreach($find as $txt){
if (strstr($text[0], $txt)) {
$counter++;
}
If i use this technique i'll have to run foreach number of times. Is there any other way to do this?
NOTE if array value contains or,and ,not not the whole word match
http://codepad.viper-7.com/VKBMtP
Input
$find=array('or','and','not');
$text=array('jasvjasvor','asmasn','tekjbdkcjbdsnot');
// array values "jasvjasvor" and "tekjbdkcjbdsnot" contains words `or,not`
Output
2 -> as two words from find array are contained in text array values

Use array_intersect():
if (count(array_intersect($find, $text)) >= 1) {
// both arrays have at least one common element
}
Demo.
UPDATE: If you're trying to find how many elements in $text array contain any of the values (partial match or whole-word match) in $find array, you can use the following solution:
$counter = 0;
foreach($find as $needle) {
foreach ($text as $haystack) {
if(strpos($haystack, $needle) !== false) $counter++;
}
}
echo $counter; // => 2
Demo.

$counter=0;
foreach($find as $txt){
foreach($txt as $value){
if (strstr($value, $txt)) {
$counter++;
}
}

Related

How to remove, just once, a word that appears several times in the array

I've researched all sorts of ways, but I haven't found a solution for this case.
Basically I have to see if the word repeats and just remove the first occurrence of it in the array. For example:
$array_words = ['harmony', 'Acrobat', 'harmony', 'harmony'];
How do I check the repeated word, just once, leaving the array like this:
$array_final = ['Acrobat', 'harmony', 'harmony'];
I threw together this simple loop, and explained it with comments
$array_words = ['harmony', 'Acrobat', 'harmony', 'harmony'];
//get a count of each word in the array
$counted_values = array_count_values($array_words);
//hold the words we have already checked
$checked_words = [];
//variable to hold our output after filtering
$output = [];
//loop over words in array
foreach($array_words as $word) {
//if word has not been checked, and appears more than once
if(!in_array($word, $checked_words) && $counted_values[$word] > 1) {
//add word to checked list, continue to next word in array
$checked_words[] = $word;
continue;
}
//add word to output
$output[] = $word;
}
$output value
Array
(
[0] => Acrobat
[1] => harmony
[2] => harmony
)
GrumpyCrouton's solution is probably neater, but here's another way. Basically you put all the values into a single string, and then use string functions to do the work.
Code is commented with explanatory notes:
<?php
$array_words = ['harmony', 'Acrobat', 'harmony', 'harmony'];
$array_words_unique = array_unique($array_words); //get a list of unique words from the original array
$array_str = implode(",", $array_words);
foreach ($array_words_unique as $word) {
//count how many times the word occurs
$count = substr_count($array_str, $word);
//if it occurs more than once, remove the first occurence
if ($count > 1) {
//find the first position of the word in the string, then replace that with nothing
$pos = strpos($array_str, $word);
$array_str = substr_replace($array_str, "", $pos, strlen($word));
}
}
//convert back to an array, and filter any blank entries caused by commas with nothing between them
$array_final = array_filter(explode(",", $array_str));
var_dump($array_final);
Demo: https://3v4l.org/i1WKI
Credit to Using str_replace so that it only acts on the first match? for code to replace only the first occurence of a string inside another string.
We can use an array to keep track of each item that has been removed, and then use array_shift to move out of the item and count to limit loop overruns
<?php
$record = ['harmony','harmony', 'Acrobat', 'harmony', 'harmony','last'];
for($i=0,$count=count($record),$stack=array();$i<$count;$i++){
$item = array_shift($record);
in_array($item,$record) && !in_array($item,$stack)
? array_push($stack,$item)
: array_push($record,$item);
}
var_dump($record);

Items in array must contain 2 dashes

Newbie here. I'm trying to make it so if $value doesn't contain two dashes then it is unset from the array. I figured out how to remove items from the array containing only ONE dash, but it needs to contain TWO. Thanks!
Removes items from an array containing only one dash:
foreach ($addkeys as $key=>&$value) {
if (strpos($value, '-') === false) {
unset($addkeys[$key]);
}
}
I also tried $value, '--' and '-''-' without success.
You need to use preg_match_all(). Here is how it would look in your code. The function returns the count of items found:
<?php
$string = "/\-/";
foreach ($addkeys as $key => &$value) {
if (preg_match_all($string, $value, &$matches)) {
if (count($matches[0]) > 1)
// greater than one.
}
}
?>

Decoding anagram with recursive function doesn't give expected output

So I'm trying to decode an anagram into words from my dictionary file. But my recursive function isn't behaving like I'm expecting.
The thoughts about the code is to eliminate letters as they are used on words and output me the string it came up with.
<?php
function anagram($string, $wordlist)
{
if(empty($string))
return;
foreach($wordlist as $line)
{
$line = $org = trim($line);
$line = str_split($line);
sort($line);
foreach($line as $key => $value)
{
if($value != $string[$key])
{
continue 2;
}
}
echo $org . anagram(array_slice($string, count($line)), $wordlist);
}
echo PHP_EOL;
}
$string = "iamaweakishspeller";
$string = str_split($string);
sort($string);
$file = file('wordlist');
anagram($string, $file);
This is my result for now, it looks awful, but I'm having some issues with the code - it's going into an indefinite loop with the same roughly 200 words from the word list.
Can someone take an extra peak at this?
Situation
You have a dictionary(file) and an anagram which contains one or multiple words. The anagram doesn't contain any punctuation or letter case of the original word(s).
Now you want to find all true solutions where you use up all characters of the anagram and decode it into word(s) from the dictionary.
Note: There is a chance that you find multiple solutions and you will never know which one the original text was and in which order the words were, since the characters of multiple words are mixed in the anagram and you don't have punctuation or the case of the letters in it.
Your code
The problem in your current code is exactly that you have multiple words mixed together. If you sort them now and you want to search them in the dictionary you won't be able to find them, since the characters of multiple words are mixed. Example:
anagram = "oatdgc" //"cat" + "dog"
wordList = ["cat", "dog"]
wordListSorted = ["act", "dgo"]
anagramSorted = acdgot
↓↓↓
WordListSorted[0] → cat ✗ no match
WordListSorted[1] → dog ✗ no match
Solution
First I will explain in theory how we construct all possible true solutions and then I explain how every part in the code works.
Theory
So to start we have an anagram and a dictionary. Now we first filter the dictionary by the anagram and only keep the words, which can be constructed by the anagram.
Then we go through all words and for each word we add it to a possible solution, remove it from the anagram, filter the dictionary by the new anagram and call the function with the new values recursively.
We do this until either the anagram is empty and we found a true solution, which we add to our solution collection, or there are no words remaining and it is not a possible solution.
Code
We have two helper functions array_diff_once() and preSelectWords() in our code.
array_diff_once() is pretty much the same as the built-in array_diff() function, except that it only removes values once and not all occurrences. Otherwise there isn't much to explain. It simply loops through the second array and removes the values once in the first array, which then gets returned.
function array_diff_once($arrayOne, $arrayTwo){
foreach($arrayTwo as $v) {
if(($key = array_search($v, $arrayOne)) !== FALSE)
array_splice($arrayOne, $key, 1);
}
return $arrayOne;
}
preSelectWords() takes an anagram and a word list as argument. It simply checks with the help of array_diff_once(), which words of the word list can be constructed with the given anagram. Then it returns all possible words from the word list, which can be constructed with the anagram.
function preSelectWords($anagram, $wordList){
$tmp = [];
foreach($wordList as $word){
if(!array_diff_once(str_split(strtolower($word)), $anagram))
$tmp[] = $word;
}
return $tmp;
}
Now to the main function decodeAnagram(). We pass the anagram and a word list, which we first filter with preSelectWords(), as arguments to the function.
In the function itself we basically just loop through the words and for each word we remove it from the anagram, filter the word list by the new anagram and add the word to a possible solution and call the function recursively.
We do this until either the anagram is empty and we found a true solution, which we add to our solution array, or there are no words left in the list and with that no possible solution.
function decodeAnagram($anagram, $wordList, $solution, &$solutions = []){
if(empty($anagram) && sort($solution) && !isset($solutions[$key = implode($solution)])){
$solutions[$key] = $solution;
return;
}
foreach($wordList as $word)
decodeAnagram(array_diff_once($anagram, str_split(strtolower($word))), preSelectWords(array_diff_once($anagram, str_split(strtolower($word))), $wordList), array_merge($solution, [$word]), $solutions);
}
Code
<?php
function decodeAnagram($anagram, $wordList, $solution, &$solutions = []){
if(empty($anagram) && sort($solution) && !isset($solutions[$key = implode($solution)])){
$solutions[$key] = $solution;
return;
}
foreach($wordList as $word)
decodeAnagram(array_diff_once($anagram, str_split(strtolower($word))), preSelectWords(array_diff_once($anagram, str_split(strtolower($word))), $wordList), array_merge($solution, [$word]), $solutions);
}
function preSelectWords($anagram, $wordList){
$tmp = [];
foreach($wordList as $word){
if(!array_diff_once(str_split(strtolower($word)), $anagram))
$tmp[] = $word;
}
return $tmp;
}
function array_diff_once($arrayOne, $arrayTwo){
foreach($arrayTwo as $v) {
if(($key = array_search($v, $arrayOne)) !== FALSE)
array_splice($arrayOne, $key, 1);
}
return $arrayOne;
}
$solutions = [];
$anagram = "aaaeeehiikllmprssw";
$wordList = ["I", "am", "a", "weakish", "speller", "William", "Shakespeare", "other", "words", "as", "well"];
//↑ file("wordlist", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)
decodeAnagram(str_split(strtolower($anagram)), preSelectWords(str_split(strtolower($anagram)), $wordList), [], $solutions);
print_r($solutions);
?>
Output
Array
(
[Iaamspellerweakish] => Array
(
[0] => I
[1] => a
[2] => am
[3] => speller
[4] => weakish
)
[ShakespeareWilliam] => Array
(
[0] => Shakespeare
[1] => William
)
)
(Ignore the keys here, since those are the identifiers of the solutions)

Check if a array have a value on specific positions

I'm getting the index keys of a haystack array containing many needles. The array contains another words too, but I don't need them to be checked.
So I'm using array_keys($haystack, &needle); to create an array containing the position of each needle.
Now I need to check in another array if on the positions from the array I've obtained by using array_keys I have a specific value. I need some ideas about how to do this.
The main idea:
$check = array_keys($haystack, &needle);
*now I need to check if I have a value on the positions from $check on $array2*
Then I need to do an action if it is found on a position (it doesn't matter on what position).
It'll work with this if it's an associative:
foreach($array1 as $k => $v)
{
if(isset($array2[$k]))
{
// Your thing
}
}
If you want to find based on the exact key index:
for($i = 0; $i < count($array1); $i++)
{
if($array1[$i] == "needle" && isset($array2[$i]))
{
if($array2[$i] == "goose")
{
// Your thing
}
}
}
You don't need to do array_keys();.
You can do it like this.
foreach ($haystack as $needle) {
if ($needle == $your_value) {
/* your stuff */
}
}

Merging two arrays, styling each a different way

I have a list of letters. I compare this list of letters against an array of the alphabet and get the difference. Then they're put together into one array so I can output it as one list.
//start the array
$alphabet = array();
//the letters I'm using
$letters = array('A','B','C','D','E','F','G','H','I','J','L','M','N','O','P','R','S','T','V');
//place into true array
foreach($letters as $l)
$alphabet['true'][] = $l;
//alphabet array, place into false array
foreach (range('A','Z') as $char)
$alphabet['false'][] = $char;
//the not used array by getting the difference of true and false arrays
$alphabet['actual'] = array_diff($alphabet['false'], $alphabet['true']);
//merge the arrays into one array
$new = array_merge($alphabet['true'],$alphabet['actual']);
//sort them naturally
natsort($new);
//list the results
echo "All together now: <pre>"; print_r($new); echo "</pre>";
Is there a way to style each of the different arrays key-values before placing them into the big array? Something along the lines of the not used letters are a different color? Or am I going about this the wrong way? Thank you for any insight.
If it where me I would do something like this.
//start the array
$alphabet = array();
//the letters I'm using
$used = array('A','B','C','D','E','F','G','H','I','J','L','M','N','O','P','R','S','T','V');
$alphabet = range('A','Z');
echo "<ul>";
foreach($alphabet as $letter){
if (in_array($letter, $used)){
echo "<li class='used'>".$letter."</li>";
} else {
echo "<li class='unused'>".$letter."</li>";
}
}
echo "</ul>";
and make a couple of css rules
li.used { color:green; }
li.unused { color:red; }

Categories