Link to home
Start Free TrialLog in
Avatar of Bruce Gust
Bruce GustFlag for United States of America

asked on

How would I parse this into an associate array?

I've got a text field with the following info being entered:

1 small onion
1 clove garlic
1 tsp basil
1/4 c olive oil

I need to parse that into something that looks like this:

[
     [
         'quantity' =>1,
         'measurement' =>'cup',
         'ingredient' => 'flour'
     ],
     [
         'quantity' =>1,
         'measurement' =>'clove',
         'ingredient' =>'garlic'
     ]
}

etc...

How...?

Thanks!
SOLUTION
Avatar of Don Thomson
Don Thomson
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Bruce Gust

ASKER

DTH! Thanks for weighing in!

Here comes my text:

1 small onion<br>1 clove garlic<br>1 tsp basil<br><br>1/4 c olive oil

When I look at something like http://www.w3schools.com/php/func_string_parse_str.asp, it seems as though the info coming in has to contain some parameters and I know that's not what I'm looking at.

How do you separate things line by line and I'll keep looking for "instring," but if you can point me in the right direction for that,  I would appreciate it.

Thanks!
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
If there are <br> tags in the data, you might want to amend the first explode() function call to take this into account.
<?php
// Example 1
$recipe  = "1 Small Onion ";
$breakdown = explode(" ", $recipe);
echo $recipe[0]; // 1
echo $recipe[1]; // Small
Echo $recipe[2]; // Onion


Once you have the items broken down into an array - you can do anything with them
Ray, I want to do my due diligence and make sure I understand what you've done and not just copy and paste things. Below are the questions / attempts to explain back to you what you recommended. If you could check that and verify my understanding, that would be great. I did have two questions that you'll see on line 49 and 60.

Thanks!

// SAMPLE DATA FROM THE POST AT E-E
$txt = <<<EOD
1 small onion
1 clove garlic
1 tsp basil
1/4 c olive oil
EOD;

// BREAK ON LINE ENDINGS
//what you're doing here is qualifying the incoming data by saying, in effect, you've got several lines of text and each line is to be processed separately as opposed to one massive pile of words
$arr = explode(PHP_EOL, $txt);

// PROCESS EACH INGREDIENT
$out = [];
/*not sure about this. I've used this kind of syntax before to set up an array which looks like this ($result_array[]=$row):
public function search_list() {

	global $mysqli;
	
		if($this->search_words=="" OR $this->search_words==" ")
		{
			header("Location:search_missing.php");
			exit();
		}
	
	$sql="select * from search_engine where keywords LIKE '%$this->search_words%' order by name";
	if(!$query=$mysqli->query($sql))
		{
			$err ='query_failure:'
			.'ERRNO: '
			.$mysqli->errno
			.'ERROR:'
			.$mysqli->error
			.PHP_EOL
			.' QUERY:'
			.$query
			.PHP_EOL;
			trigger_error($err, E_USER_WARNING);
		}
	$result_array=array();

	while($row=$query->fetch_array())
		{
			$result_array[]=$row;
		}
	return $result_array;
	}		

What's the difference? It's looks as though you're setting up a digital container of sorts, but then that seems to be happening on line 67. 
*/
foreach ($arr as $itm)
{
    // NORMALIZE TO SINGLE BLANKS
    $itm = preg_replace('/\s\s+/', ' ', $itm);
    $itm = trim($itm);

    // BREAK ON BLANKS AND ISOLATE EACH ELEMENT
	//with "explode," you're now taking the normalized entry and breaking it up into an array that consists of three separate entities separated by a space
    $itm = explode(' ', $itm);
	/*here's where I wanted to really pop the hood and understand what you were doing. Based on http://php.net/manual/en/function.implode.php, it looks like implode returns the $itm array as a string. The elements within that string being $qty, $mes and $ing. You're calling a function that is referenced on the post you made out at http://php.net/manual/en/function.array-slice.php. It seems like you're sequentially "chopping" the array down into bits that are then returned as the part of the $itm string that corresponds to either $qty, $mes and $ing. It works becasue of the way implode feeds each of those elements in their appropriate order
	*/
	
    $qty = implode(NULL, array_chop($itm));
    $mes = implode(NULL, array_chop($itm));
    $ing = implode(' ', $itm);
	//now you're taking those three strings and assembling them into an array that will be neatly packaged for however many lines the user entered
    $out[] = array
    ( 'quantity'    => $qty
    , 'measurement' => $mes
    , 'ingredient'  => $ing
    )
    ;
}
echo json_encode($out, JSON_PRETTY_PRINT);

function array_chop(&$arr, $num=1)
{
    $ret = array_slice($arr, 0, $num);
    $arr = array_slice($arr, $num);
    return $ret;
}

echo json_encode($out, JSON_PRETTY_PRINT);

function array_chop(&$arr, $num=1)
{
    $ret = array_slice($arr, 0, $num);
    $arr = array_slice($arr, $num);
    return $ret;
}

Open in new window

Comments interspersed below.  Please post back if you still have any questions about the ideas here.
// SAMPLE DATA FROM THE POST AT E-E
$txt = <<<EOD
1 small onion
1 clove garlic
1 tsp basil
1/4 c olive oil
EOD;

// BREAK ON LINE ENDINGS
//what you're doing here is qualifying the incoming data by saying, in effect, you've got several lines of text and each line is to be processed separately as opposed to one massive pile of words
//***--> Exactly.  PHP explode() turns strings into arrays.  PHP_EOL is the end-of-line character.
$arr = explode(PHP_EOL, $txt);

// PROCESS EACH INGREDIENT
$out = [];
/*not sure about this. I've used this kind of syntax before to set up an array which looks like this ($result_array[]=$row):
//***--> The two square brackets have the same meaning as array(). This newer notation more closely matches the array notation in other languages, notably JavaScript.
public function search_list() {

	//***--> NEVER use the "global" keyword.  It makes your script untestable.  Learn about DEPENDENCY INJECTION and PHP UNIT TESTING.  You can thank me later!
	global $mysqli;
	
	        //***--> $this-> implies that this code is inside an object instance of a class
		if($this->search_words=="" OR $this->search_words==" ")
		{
			header("Location:search_missing.php");
			exit();
		}
	
	//***--> Might want to add a LIMIT clause here - performance will matter if you have a lot of activity on the site and a lot of information in the table
	$sql="select * from search_engine where keywords LIKE '%$this->search_words%' order by name";
	if(!$query=$mysqli->query($sql))
		{
			$err ='query_failure:'
			.'ERRNO: '
			.$mysqli->errno
			.'ERROR:'
			.$mysqli->error
			.PHP_EOL
			.' QUERY:'
			.$query
			.PHP_EOL;
			trigger_error($err, E_USER_WARNING);
		}
	$result_array=array();

	while($row=$query->fetch_array())
		{
			$result_array[]=$row;
		}
	return $result_array;
	}		

What's the difference? It's looks as though you're setting up a digital container of sorts, but then that seems to be happening on line 67. 
*/

//***--> This iterates over the $arr array (created by explode() above)
foreach ($arr as $itm)
{
    // NORMALIZE TO SINGLE BLANKS
    $itm = preg_replace('/\s\s+/', ' ', $itm);
    $itm = trim($itm);

    // BREAK ON BLANKS AND ISOLATE EACH ELEMENT
	//with "explode," you're now taking the normalized entry and breaking it up into an array that consists of three separate entities separated by a space
    //***--> We are breaking the $itm string on each space into an array that consists of "n" separate array elements.  We do not know how many such elements there may be.
    //***--> We are assigning this array to the $itm variable, since we do not need it to be a string any more.  We need the array so we can work with each element separately.
    $itm = explode(' ', $itm);
	/*here's where I wanted to really pop the hood and understand what you were doing. Based on http://php.net/manual/en/function.implode.php, it looks like implode returns the $itm array as a string. The elements within that string being $qty, $mes and $ing. You're calling a function that is referenced on the post you made out at http://php.net/manual/en/function.array-slice.php. It seems like you're sequentially "chopping" the array down into bits that are then returned as the part of the $itm string that corresponds to either $qty, $mes and $ing. It works becasue of the way implode feeds each of those elements in their appropriate order
	*/

    //***--> The local function array_chop() returns an array.  When it return an array of one element, and we want that element to be a string, implode(NULL) will turn the one element of the array into a string.
    //***--> array_chop() also removes the element from the array, shortening the array.  The first two elements of the array are important positions.  The 3rd and subsequent elements all wind up in the "ingredient" part.
    $qty = implode(NULL, array_chop($itm));
    $mes = implode(NULL, array_chop($itm));
    $ing = implode(' ', $itm);
    
    //now you're taking those three strings and assembling them into an array that will be neatly packaged for however many lines the user entered
    //***--> Exactly.  The square bracket notation says "create a new array element in the $out variable."
    //***--> The new element of $out is an associative array with quantity, measurement, and incredient.
    //***--> There is no such thing as an associative array in JavaScript nor in JSON.  The conversion to JSON makes the associative arrays into objects.
    $out[] = array
    ( 'quantity'    => $qty
    , 'measurement' => $mes
    , 'ingredient'  => $ing
    )
    ;
}
echo json_encode($out, JSON_PRETTY_PRINT);

function array_chop(&$arr, $num=1)
{
    $ret = array_slice($arr, 0, $num);
    $arr = array_slice($arr, $num);
    return $ret;
}

Open in new window