php store array in array by reference - php

I have the following problem. There are some php lines.
In the var_dump of $testArrayA, the "def" entry with test2 is NOT there because it was added
after $testArrayB was added to $testArrayA.
It seems to me that in my case, that $testArrayB is not stored by reference in $testArrayA. How can I store it per reference, what do I have to make to have "def" entry in the var_dump?
Thanks alot in advance
$testArrayA = [];
$testArrayB = [];
$testArrayB["ghi"] = "test1";
$testArrayA["abc"] = $testArrayB;
$testArrayB["def"] = "test2";
The var_dump:
array(1) {
["abc"]=>
array(1) {
["ghi"]=>
string(5) "test1"
}
}

This is simply a matter of passing by reference:
$testArrayA = [];
$testArrayB = [];
$testArrayB["ghi"] = "test1";
$testArrayA["abc"] = &$testArrayB;
$testArrayB["def"] = "test2";
var_dump($testArrayA);
array (size=1)
'abc' => &
array (size=2)
'ghi' => string 'test1' (length=5)
'def' => string 'test2' (length=5)

Use:
$testArrayA["abc"] = &$testArrayB;
Note:
Different with C's pointer, references in PHP are a means to access the same variable content by different names.

in the php manual
Array assignment always involves value copying. Use the reference operator to copy an array by reference.

$testArrayA = null;
$testArrayB = null;
$testArrayB["ghi"] = "test1";
$testArrayA["abc"] = $testArrayB;
$testArrayB["def"] = "test2";
print_r($testArrayA);
echo ("<br>");
print_r($testArrayB);
Array ( [abc] => Array ( [ghi] => test1 ) )
Array ( [ghi] => test1 [def] => test2 )
The 'def' entry is a different reference with the 'ghi',
but they all belong testArrayB.
$testArrayA["abc"] = $testArrayB;
This code only is value reference ,not address reference.

Related

Group values of array according to regex in PHP

I have an array that looks like this:
[0] => name {
[1] => abc
[2] => def
[3] => }
[4] =>
[5] => othername {
[6] => 123
[7] => 456
[8] => 789
[9] => }
[10] =>
As you can see each group (under each name) can have different amount of lines and different items in them but each group starts with the same regex syntax and ends with a closing } and a blank line after that.
I need to get an array for each group (for each name) recursively. I made a preg_match regex that will find each name line but I don't know how to make an array with that having also all the lines that are before the next name group.
So I want to obtain:
array(
array('name {', 'abc', 'def', '}'),
array('othername {', '123', '456', '789', '}')
)
How can I approach this? Thanks in advance.
Clicquot beat me but I'm not sure his works/is tested. Here's my solution
<?php
$array = array('0' => 'name {', '1' => 'abc', '2' => 'def', '3' => "}\n", '4' => "\n",
'5' => 'othername {',
'6' => '123',
'7' => '456',
'8' => '789',
'9' => '}',
'10' => "\n");
$string = array();
$count = 0;
foreach($array as $value){
$value = trim($value);
$pos = strpos($value, '{');
if ($pos !== false) {
$count++;
}
if(!empty($value)) {
$string[$count][] = $value;
}
}
print_r($string);
Maybe this code is what you asked for. But I'd never use it myself. If you try to build a code parser you shuold look for parsing-trees with a "grammar" or syntax analysis. It is part of parsing and compilers. The slide bellow shows how a compiler or interpreter can work. If you are only aiming to represent your data in order to reach some specific goal, maybe you can look at formats like json. You should always mention in one sentence what your overall goal is prior to asking a specific question.
(sorry for the German)
The issues of the code below are, that syntax variations can break the code, and you are highly voulnerable because the code changes your php variable contents concerning to the contents of your array.
If you are processing a file with code I do recommend you also to process it streight away, instead of first saving it to an array (which costs more memory).
<?php
$syntaxArray = array(
0 => 'name {',
1 => 'abc',
2 => 'def',
3 => '}',
4 => 'othername {',
5 => '123',
6 => '456',
7 => '789',
8 => '}'
);
$regex_open_array = '-(\w+)\s*{-';
$array_open = false;
foreach($syntaxArray as $line){
$matches = array();
if( preg_match($regex_open_array, $line, $matches) ){
if($array_open){
/*recursive array creations do not work - if that's what you need put it in the comments*/
throw new RuntimeException('An array can not be open while the previous array is not closed');
}
$array_open = true;
/*create an array variable
* ....
* isolate the variable name
*/
$currentArray = $matches[1];
/*you can either create a new variable in your php code with the array name or use a big array and use the name as key
* $big_array[$name] = array();
* using this solution every array name must be only used once.
* of course you can use a name twice if you first check prior to creating a new array if the key is already in use.
*/
/*creates a variable with the given name. Must not overwrite an other arrays name like $syntaxArray*/
$$currentArray = array();
}else if($line == '}'){
/*the closing string could be wrapped with trim() or matched with a regex but I followed your example*/
$array_open = false;
}else{
if(!$array_open){
throw new RuntimeException('There is not array currently open');
}
$arr = &$$currentArray;
$arr[] = $line;
}
}
var_dump($name);
var_dump($othername);
Outputs:
array(2) { [0]=> string(3) "abc" [1]=> string(3) "def" } array(3) { [0]=> string(3) "123" [1]=> string(3) "456" [2]=> string(3) "789" }
This isn't really a regex thing. What you want to do is iterate through the array, and check each item. You'd search through the value there for a '{' or a '}'. When you see an opening bracket, you'd set the key in your "condensed" array that you want to index into, and then check subsequent items for a closing bracket. When you see the closing bracket, you'd change the key that you're indexing into in your "condensed" array or whatever and begin anew. When the value isn't a bracket, append it. It'll look something like this (sorry for the bad PHP):
$big_array = array();
$temp_key = NULL;
foreach (array as $key => $value) {
if (strpo($value, '{')) {
$big_array[$key] = array();
$temp_key = $key;
} else if (strpos($value, '}')) {
$temp_key = NULL;
} else {
$big_array[$temp_key].append($value); // or whatever
}
}
This assumes that you having a matching open / close bracket structure , you'd want to add in a ton of error checking of course.

Assign array key's value to another key of the same array PHP

When creating an array, is there any way I could assign a key's value to another key in the same array?
For example:
<?php
$foobarr = array (
0 => 'foo',
1 => $foobarr[0] . 'bar',
);
?>
In this example $foobarr[1] holds the value 'bar'.
Any way I can do this so that $foobarr[1] == 'foobar'?
No, you can't do that, because the array hasn't been constructed yet when you try to reference it with $foobarr[0].
You could save 'foo' to another variable though, and just use that:
$foo = 'foo';
$foobarr = array (
0 => $foo,
1 => $foo . 'bar',
);
You can do it if you assign the keys individually:
$foobarr = array();
$foobarr[0] = 'foo';
$foobarr[1] = $foobarr[0] . 'bar';
etc. But not all at once inside the initializer - the array doesn't exist yet in there.
Sure, you'd need to reference it outside though.
$foobarr = array (
0 => 'foo'
);
$foobarr[1] = $foobarr[0] . 'bar';

Add 2 values to 1 key in a PHP array

I have a result set of data that I want to write to an array in php. Here is my sample data:
**Name** **Abbrev**
Mike M
Tom T
Jim J
Using that data, I want to create an array in php that is of the following:
1|Mike|M
2|Tom|T
3|Jim|j
I tried array_push($values, 'name', 'abbreviation') [pseudo code], which gave me the following:
1|Mike
2|M
3|Tom
4|T
5|Jim
6|J
I need to do a look up against this array to get the same key value, if I look up "Mike" or "M".
What is the best way to write my result set into an array as set above where name and abbreviation share the same key?
PHP's not my top language, but try these:
array_push($values, array("Mike", "M"))
array_push($values, array("Tom", "T"))
array_push($values, array("Jim", "J"))
$name1 = $values[1][0]
$abbrev1 = $values[1][1]
or:
array_push($values, array("name" => "Mike", "abbrev" => "M"))
array_push($values, array("name" => "Tom", "abbrev" => "T"))
array_push($values, array("name" => "Jim", "abbrev" => "J"))
$name1 = $values[1]["name"]
$abbrev1 = $values[1]["abbrev"]
The trick is to use a nested array to pair the names and abbreviations in each entry.
$person = array('name' => 'Mike', 'initial' => 'M');
array_push($people, $person);
That said, I'm not sure why you're storing the data separately. The initial can be fetched directly from the name via substr($name, 0, 1).
You will need to create a two dimensional array to store more than one value.
Each row in your result set is already an array, so it will need to be added to your variable as an array.
array_push($values, array('name', 'abbreviation'));
maybe you create a simple class for that as the abbreviation is redundant information in your case
class Person
{
public $name;
pulbic function __construct($name)
{
$this->name = (string)$name;
}
public function getAbbrev()
{
return substr($this->name, 0, 1);
}
public function __get($prop)
{
if ($prop == 'abbrev') {
return $this->getAbbrev();
}
}
}
$persons = array(
new Person('Mike'),
new Person('Tom'),
new Person('Jim')
);
foreach ($persons as $person) {
echo "$person->name ($person->abbrev.)<br/>";
}
You could use two separate arrays, maybe like:
$values_names = array();
$values_initials = array();
array_push($values_names, 'Mike');
array_push($values_initials, 'M');
array_push($values_names, 'Tom');
array_push($values_initials, 'T');
array_push($values_names, 'Jim');
array_push($values_initials, 'J');
So you use two arrays, one for each of the second and third columns using the values in the first one as keys for both arrays.
php arrays work like hash lookup tables, so in order to achieve the desired result, you can initialize 2 keys, one with the actual value and the other one with a reference pointing to the first. For instance you could do:
$a = array('m' => 'value');
$a['mike'] = &$a['m']; //notice the end to pass by reference
if you try:
$a = array('m' => 'value');
$a['mike'] = &$a['m'];
print_r($a);
$a['m'] = 'new_value';
print_r($a);
$a['mike'] = 'new_value_2';
print_r($a);
the output will be:
Array
(
[m] => value
[mike] => value
)
Array
(
[m] => new_value
[mike] => new_value
)
Array
(
[m] => new_value_2
[mike] => new_value_2
)
have to set the same value to both Mike and M for keys.

array_push() with key value pair

I have an existing array to which I want to add a value.
I'm trying to achieve that using array_push() to no avail.
Below is my code:
$data = array(
"dog" => "cat"
);
array_push($data['cat'], 'wagon');
What I want to achieve is to add cat as a key to the $data array with wagon as value so as to access it as in the snippet below:
echo $data['cat']; // the expected output is: wagon
How can I achieve that?
So what about having:
$data['cat']='wagon';
If you need to add multiple key=>value, then try this.
$data = array_merge($data, array("cat"=>"wagon","foo"=>"baar"));
$data['cat'] = 'wagon';
That's all you need to add the key and value to the array.
You don't need to use array_push() function, you can assign new value with new key directly to the array like..
$array = array("color1"=>"red", "color2"=>"blue");
$array['color3']='green';
print_r($array);
Output:
Array(
[color1] => red
[color2] => blue
[color3] => green
)
For Example:
$data = array('firstKey' => 'firstValue', 'secondKey' => 'secondValue');
For changing key value:
$data['firstKey'] = 'changedValue';
//this will change value of firstKey because firstkey is available in array
output:
Array ( [firstKey] => changedValue [secondKey] => secondValue )
For adding new key value pair:
$data['newKey'] = 'newValue';
//this will add new key and value because newKey is not available in array
output:
Array ( [firstKey] => firstValue [secondKey] => secondValue [newKey]
=> newValue )
Array['key'] = value;
$data['cat'] = 'wagon';
This is what you need.
No need to use array_push() function for this.
Some time the problem is very simple and we think in complex way :) .
<?php
$data = ['name' => 'Bilal', 'education' => 'CS'];
$data['business'] = 'IT'; //append new value with key in array
print_r($data);
?>
Result
Array
(
[name] => Bilal
[education] => CS
[business] => IT
)
Just do that:
$data = [
"dog" => "cat"
];
array_push($data, ['cat' => 'wagon']);
*In php 7 and higher, array is creating using [], not ()

php array_merge without erasing values?

Background: Trevor is working with a PHP implementation of a standard algorithm: take a main set of default name-value pairs, and update those name-value pairs, but only for those name-value pairs where a valid update value actually exists.
Problem: by default, PHP array_merge works like this ... it will overwrite a non-blank value with a blank value.
$aamain = Array('firstname'=>'peter','age'=>'32','nation'=>'');
$update = Array('firstname' => '','lastname' => 'griffin', age =>'33','nation'=>'usa');
print_r(array_merge($aamain,$update));
/*
Array
(
[firstname] => // <-- update set this to blank, NOT COOL!
[age] => 33 // <-- update set this to 33, thats cool
[lastname] => griffin // <-- update added this key-value pair, thats cool
[nation] => usa // <-- update filled in a blank, thats cool.
)
*/
Question: What's the fewest-lines-of-code way to do array_merge where blank values never overwrite already-existing values?
print_r(array_coolmerge($aamain,$update));
/*
Array
(
[firstname] => peter // <-- don't blank out a value if one already exists!
[age] => 33
[lastname] => griffin
[nation] => usa
)
*/
UPDATE: 2016-06-17T11:51:54 the question was updated with clarifying context and rename of variables.
Well, if you want a "clever" way to do it, here it is, but it may not be as readable as simply doing a loop.
$merged = array_merge(array_filter($foo, 'strval'), array_filter($bar, 'strval'));
edit: or using +...
array_replace_recursive($array, $array2);
This is the solution.
Try this:
$merged = array_map(
create_function('$foo,$bar','return ($bar?$bar:$foo);'),
$foobar,$feebar
);
Not the most readable solution, but it should replace only non-empty values, regardless of which order the arrays are passed..
Adjust to your needs:
# Replace keys in $foo
foreach ($foo as $key => $value) {
if ($value != '' || !isset($bar[$key])) continue;
$foo[$key] = $bar[$key];
}
# Add other keys in $bar
# Will not overwrite existing keys in $foo
$foo += $bar;
If you also want to keep the values that are blank in both arrays:
array_filter($foo) + array_filter($bar) + $foo + $bar
This will put duplicates into a new array, I don't know if this is what you want though.
<?php
$foobar = Array('firstname' => 'peter','age' => '33',);
$feebar = Array('firstname' => '','lastname' => 'griffin',);
$merged=$foobar;
foreach($feebar as $k=>$v){
if(isset($foobar[$k]))$merged[$k]=array($v,$foobar[$k]);
else $merged[$k]=$v;
}
print_r($merged);
?>
This will simply assure that feebar will never blank out a value in foobar:
<?php
$foobar = Array('firstname' => 'peter','age' => '33',);
$feebar = Array('firstname' => '','lastname' => 'griffin',);
$merged=$foobar;
foreach($feebar as $k=>$v) if($v)$merged[$k]=$v;
print_r($merged);
?>
or ofcourse,
<?
function cool_merge($array1,$array2){
$result=$array1;
foreach($array2 as $k=>$v) if($v)$result[$k]=$v;
return $result;
}
$foobar = Array('firstname' => 'peter','age' => '33',);
$feebar = Array('firstname' => '','lastname' => 'griffin',);
print_r(cool_merge($foobar,$feebar));
?>

Categories