Jump to content

converting strings from foreach into a single array


Go to solution Solved by QuickOldCar,

Recommended Posts

Hi all,

I am using foreach statement to gather records and program levenshtein to detect any misspellings and suggesting the correct words.

 

The thing is i am unable to convert all those strings into a single array.

 

After trying to correct this issue so many times, i wonder if it is really possible to convert strings into a single array?

 

Any input is welcome :) 

Difficult to determine what you're after unless you post some code. There are many ways to convert strings into arrays. The whole string or just words/parts of the string. Post some code and a clear explanation of what you're trying to accomplish and let's get the party started!

$string = "This is a string, whatever";
$args = explode(' ', $string);
print_r( $args );

// output:
Array ( [0] => This [1] => is [2] => a [3] => string, [4] => whatever ) 

$string = "Sentence number one. Sentence number two. Sentence number 3.";
$args = explode('.', $string);
$sentence_array = array();

foreach($args as $sentence)
{
    if($sentence.length < 3) { continue; }
    $sentence_array[] = trim($sentence) . '.';
}
print_r($sentence_array);

// output: 
Array ( [0] => Sentence number one. [1] => Sentence number two. [2] => Sentence number 3. )

Here is the code, the first part of the code outputs as separate strings. what i am trying to achieve is to convert all those values to a single array to check against using levenshtein. Currently it only checks against and provides only one suggestion, the last value of the string. is there any solution to this?
 
the code is below:

<?php
$search = "";
if(isset($_GET["s"])) {
	$search = trim(htmlspecialchars($_GET["s"])); }
	if($search != "") {
	echo "<h1>Search term is set to <abbr style='text-transform:capitalize;'>{$search}</abbr></h1>"; 
	}

?>


<form action="index.php">
    <input type="text" name="s"  value="<?php echo $searchterm; ?>"/>
    <input type="submit" value="GO"  />
    </form>

<?php
$cakes = array();
$cakes = array(
	"jade" => array(
		"Chocolate Cake" => array(
			"ingredients" => "Chocolate, eggs, flour"),
		"Cookie Dough Cake" => array(
			"ingredients" => "Cookies, Double cream, flour, eggs")
			),
	"jessica" => array(
		"Lemon Cheesecake" => array(
			"ingredients" => "Lemon, eggs, flour"),
		"Belgian Chocolate Cake" => array(
			"ingredients" => "Dark belgian chocolate, eggs, flour")
			),
	"stephanie" => NULL,
);

foreach($cakes as $cakeid => $cake)
if(!empty($cake))
foreach($cake as $cakenames => $cakedescriptions)
	{
$pieces = explode(",", $cakenames);
foreach($pieces as $cakename) {
var_dump($cakename); 
		}
	}


$input = $search;
$words  = array($cakename);

//array('apple','pineapple','banana','orange',
//                'radish','carrot','pea','bean','potato');
// no shortest distance found, yet
$shortest = -1;


// loop through words to find the closest
foreach ($words as $word) {

    // calculate the distance between the input word,
    // and the current word
    $lev = levenshtein($input, $word);

    // check for an exact match
    if ($lev == 0) {

        // closest word is this one (exact match)
        $closest = $word;
        $shortest = 0;

        // break out of the loop; we've found an exact match
        break;
    }

    // if this distance is less than the next found shortest
    // distance, OR if a next shortest word has not yet been found
    if ($lev <= $shortest || $shortest < 0) {
        // set the closest match, and shortest distance
        $closest  = $word;
        $shortest = $lev;
    }
}

echo "Input word: $input\n";
if ($shortest == 0) {
    echo "Exact match found: $closest\n";
} else {
    echo "Did you mean: $closest?\n";
}



?>


  • Solution

This isn't the greatest thing to do as arrays can get huge, more work just to check for a typo.

Lucene has this built in using fuzzy searches

<?php

if (isset($_GET['s']) && trim($_GET['s']) != '') {
    $search = strtolower(trim($_GET['s']));
} else {
    $search = '';
}

?>


<form action="" method="get">
    <input type="text" name="s" value="<?php echo $search;?>"/>
    <input type="submit" value="GO"  />
</form>

<?php
$cakes = array(
    "jade" => array(
        "Chocolate Cake" => array(
            "ingredients" => "Chocolate, eggs, flour"
        ),
        "Cookie Dough Cake" => array(
            "ingredients" => "Cookies, Double cream, flour, eggs"
        )
    ),
    "jessica" => array(
        "Lemon Cheesecake" => array(
            "ingredients" => "Lemon, eggs, flour"
        ),
        "Belgian Chocolate Cake" => array(
            "ingredients" => "Dark belgian chocolate, eggs, flour"
        )
    ),
    "stephanie" => NULL
);

$string = ''; //keep blank

//find each word from the array values
foreach ($cakes as $val) {
   
    if (is_array($val)) {
        foreach ($val as $key => $val2) {
            $string .= $key . " ";
           
            if (is_array($val)) {
                foreach ($val2 as $key => $val3) {
                    if ($val3 != NULL || trim($val3) != '') {
                        $string .= str_replace(",", " ", $val3) . " ";
                    }
                   
                   
                }
            }
           
           
           
        }
    }
   
}


//remove whitespace and multiple spaces
$string = preg_replace('/\s+/', ' ', strtolower(trim($string)));

//explode the spaces in string and create an array
$suggestions = array();
$suggestions = explode(" ", $string);

$levenshtein = array();
//loop the suggestions array against levenshtein
foreach ($suggestions as $suggestion) {
    $levenshtein[$suggestion] = levenshtein($search, $suggestion);
}

if (!empty($levenshtein)) {
    //sorted by lowest number of changes
    asort($levenshtein, SORT_NUMERIC);
   
    //show all weighted results
    echo "<pre>";
    print_r($levenshtein);
    echo "</pre>";
   
    //show only the closest results
    foreach ($levenshtein as $suggestion => $weight) {
        //weights of 1 or 2 usually the closest matches, zero is an exact match
        if ($weight > 0 && $weight < 3) {
            echo $suggestion . "<br />";
        }
    }
   
}
?>

searching for coookie returns

Array
(
    [cookie] => 1
    [cookies] => 2
    [cake] => 4
    [chocolate] => 5
    [double] => 5
    [lemon] => 6
    [dark] => 6
    [dough] => 6
    [cream] => 6
    [flour] => 6
    [belgian] => 7
    [eggs] => 7
    [cheesecake] => 8
)

cookie
cookies

You could remove this section and not do ingredients.

if (is_array($val)) {
                foreach ($val2 as $key => $val3) {
                    if ($val3 != NULL || trim($val3) != '') {
                        $string .= str_replace(",", " ", $val3) . " ";
                    }
                  
                  
                }
            }

 

You could remove this section and not do ingredients.

if (is_array($val)) {
                foreach ($val2 as $key => $val3) {
                    if ($val3 != NULL || trim($val3) != '') {
                        $string .= str_replace(",", " ", $val3) . " ";
                    }
                  
                  
                }
            }

 

as opposed to separating each word and matching it to a search term, is it possible to suggest the individual cake names (ie. chocolate cake, lemon chesecake...) ? the reason i ask is because i tried toying with the explode string and it returns a blank value (nothing seems to be returned).

I did it for complete words and trying to find close matches within the multiple words.

 

Hopefully this helps you closer to what you need.

<?php

if (isset($_GET['s']) && trim($_GET['s']) != '') {
    $search = strtolower(trim($_GET['s']));
} else {
    $search = '';
}

?>


<form action="" method="get">
    <input type="text" name="s" value="<?php
echo $search;
?>"/>
    <input type="submit" value="GO"  />
</form>

<?php
$cakes = array(
    "jade" => array(
        "Chocolate Cake" => array(
            "ingredients" => "Chocolate, eggs, flour"
        ),
        "Cookie Dough Cake" => array(
            "ingredients" => "Cookies, Double cream, flour, eggs"
        )
    ),
    "jessica" => array(
        "Lemon Cheesecake" => array(
            "ingredients" => "Lemon, eggs, flour"
        ),
        "Belgian Chocolate Cake" => array(
            "ingredients" => "Dark belgian chocolate, eggs, flour"
        )
    ),
    "stephanie" => NULL
);

$string      = ''; //keep blank
$levenshtein = array();
$exploded    = array();
//find each word from the array values
foreach ($cakes as $val) {
    
    if (is_array($val)) {
        foreach ($val as $key => $val2) {
            if (is_array($val)) {
                //explode multiple words
                $exploded = explode(" ", strtolower(trim($key)));
                if (!empty($exploded)) {
                    //loop each exploded word
                    foreach ($exploded as $explode) {
                        //get each words weight
                        $lev_weight = levenshtein($search, $explode);
                        //if any of the words within range, add complete words to array
                        if ($lev_weight >= 0 && $lev_weight <= 3) {
                            
                            $levenshtein[$key] = $lev_weight;
                            
                        }
                        
                    }
                }                
               
            }
            
            
        }
    }
    
}

//only show if not an empty array
if (!empty($levenshtein)) {
    
    asort($levenshtein, SORT_NUMERIC);
    
    //show raw results
    echo "<pre>";
    print_r($levenshtein);
    echo "</pre>";
    
    //loop items from array
    foreach ($levenshtein as $word => $weight) {
        echo $word . "<br />";
        echo $weight . "<br />";
    }
    
}
?> 

results for chocolate

 

Array
(
    [belgian Chocolate Cake] => 0
    [Chocolate Cake] => 0
)

Belgian Chocolate Cake
0
Chocolate Cake
0

Edited by QuickOldCar
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.