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!
brucegustPHP DeveloperAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Don ThomsonCommented:
For the majority of items - there are 3 fields
Qty
Measurement
Item

However the third item is 1/4 cup Olive Oil
Here you have 4 fields

As long as the first two fields are always Qty and Measurement you shouldn't have any problems

Just do an instring  for the space
Say in the first item the first space is at position 2
Then look for middle sting of " " starting at position 2+1   the 2 being the first space
the value of the first string of " " would be 2   so you grab the Left(string,1)  IF the value was 23  then the position of the first " " would be 3 - so you take the 1st 2 numbers  (Pos of " " -1

Once you have the second " "  the rest is easy  - Say Position of the 2nd " "  is 8 then the last filed would be a Mid(string, 8+1, )

IF you have a lot of the C for Cup - Translate the c to Cup during the parsing.
0
brucegustPHP DeveloperAuthor Commented:
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!
0
Ray PaseurCommented:
As always when parsing text, the devil is in the details, and rigidity of computer programming is often at odds with natural language.  What can you do with a recipe that calls for "2 or 3 cloves of garlic?"

Please see http://iconoun.com/demo/temp_brucegust.php
<?php // demo/temp_brucegust.php
/**
 * http://www.experts-exchange.com/questions/28704361/How-would-I-parse-this-into-an-associate-array.html
 * http://php.net/manual/en/function.array-slice.php#112359
 */
error_reporting(E_ALL);
echo '<pre>';

// 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
$arr = explode(PHP_EOL, $txt);

// PROCESS EACH INGREDIENT
$out = [];
foreach ($arr as $itm)
{
    // NORMALIZE TO SINGLE BLANKS
    $itm = preg_replace('/\s\s+/', ' ', $itm);
    $itm = trim($itm);

    // BREAK ON BLANKS AND ISOLATE EACH ELEMENT
    $itm = explode(' ', $itm);
    $qty = implode(NULL, array_chop($itm));
    $mes = implode(NULL, array_chop($itm));
    $ing = implode(' ', $itm);
    $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

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Cloud Class® Course: Certified Penetration Testing

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

Ray PaseurCommented:
If there are <br> tags in the data, you might want to amend the first explode() function call to take this into account.
0
Don ThomsonCommented:
<?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
0
brucegustPHP DeveloperAuthor Commented:
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

0
Ray PaseurCommented:
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

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.