I have a two-dimensional array:
array(
array(
'Friend',
'Amigo',
'',
''
),
array(
'Friend',
'',
'Fraund',
''
),
array(
'Thanks',
'Gracias',
'',
''
),
array(
'Thanks',
'',
'Danke',
''
)
);
Basically, I need to combine inner arrays when they have the same values in a corresponding order. For example, 'friend' and 'thanks' in a current example. Output should be:
array(
array(
'Friend',
'Amigo',
'Fraund',
''
),
array(
'Thanks',
'Gracias',
'Danke',
''
)
);
Thus, the empty element needs to be overwritten by the corresponding element which has got some value. Cannot figure out how to do it with array_merge.
You could use array_reduce() like this:
$result = array_values(array_reduce($a, function(array &$final, $current) {
$key = $current[0];
if (isset($final[$key])) {
// replace items that are not an empty string
$final[$key] = array_replace($final[$key], array_filter($current, 'strlen'));
} else {
$final[$key] = $current;
}
return $final;
}, []));
The reduce operation creates an array whereby the first word of each array is used as the key; array_replace() updates existing values with new ones if the string is not empty.
The end result is then pulled through array_values() to get rid of the temporary keys that were used during the reduce operation.
Well, I'd go about it like this
$final_array = array();
$original_array = array(
array(
'Friend',
'Amigo',
'',
''
),
array(
'Friend',
'',
'Fraund',
''
),
array(
'Thanks',
'Gracias',
'',
''
),
array(
'Thanks',
'',
'Danke',
''
)
);
$friends_array = array();
foreach($original_array[0] as $row) {
if($row != "") {
array_push($friends_array, $row);
}
}
foreach($original_array[1] as $row) {
if($row != "" && !in_array($row, $friends_array)) {
array_push($friends_array, $row);
}
}
$thanks_array = array();
foreach($original_array[2] as $row) {
if($row != "") {
array_push($thanks_array, $row);
}
}
foreach($original_array[3] as $row) {
if($row != "" && !in_array($row, $thanks_array)) {
array_push($thanks_array, $row);
}
}
array_push($final_array, $friends_array, $thanks_array);
You do have a very specific request. Rather odd tbh.
Iterate the array, add the values to a new array (indexed by the 1st element in the internal arrays), then use array_values to get your desired output (or leave it indexed as is, which may be beneficial for further data access):
$out = [];
foreach ($input as $val) {
$key = $val[0];
foreach ($val as $item) {
if(!empty($item) && $item !=$key){
$out[$key][]=$item;
}
}
if(!in_array($key, $out[$key])) $out[$key][]=$key;
}
$out = array_values($out);
var_dump($out);
Live working example:
http://codepad.viper-7.com/EoRhh2
in php you can use
array_unique($arr1,$arr2);
or
array_merge($arr1,$arr2);
But in your condition you ahve a single array which you have to split into different arrays
$mainArary = array(
array(
'Friend',
'Amigo',
'',
''
),
array(
'Friend',
'',
'Fraund',
''
),
array(
'Thanks',
'Gracias',
'',
''
),
array(
'Thanks',
'',
'Danke',
''
)
);
$first_array = null;
$second_array = null;
$i = 0;
foreach($mainArray[0] as $arr){
if($i < 2){
if($prev_array == null){
$prev_array = $arr;
} else {
$prev_array = array_merge($prev_array,$arr);
} } else {
if($second_array == null){
$second_array = $arr;
} else {
$second_array = array_merge($second_array ,$arr);
}
}
}
print_r($prev_array);
print_r($second_array);
Here is your desired output.
Related
I have an array like below
$db_resources = array('till' => array(
'left.btn' => 'Left button',
'left.text' => 'Left text',
'left.input.text' => 'Left input text',
'left.input.checkbox' => 'Left input checkbox'
));
I need to convert this array dynamically like below
'till' => array(
'left' => array(
'btn' => 'Left button',
'text' => 'Left text',
'input' => array(
'text' => 'Left input text',
'checkbox' => 'Left input checkbox'
)
)
)
I tried the key with explode. it works if all the key has only one ".". But the key has dynamic one. so please hep me to convert the array dynamically. I tried this Below Code
$label_array = array();
foreach($db_resources as $keey => $db_resources2){
if (strpos($keey,'.') !== false) {
$array_key = explode('.',$keey);
$frst_key = array_shift($array_key);
if(count($array_key) > 1){
$label_array[$frst_key][implode('.',$array_key)] = $db_resources2;
//Need to change here
}else{
$label_array[$frst_key][implode('.',$array_key)] = $db_resources2;
}
}
}
There might be more elegant ways to go about it, but here is one example of doing it with recursive helper function:
function generateNew($array, $keys, $currentIndex, $value)
{
if ($currentIndex == count($keys) - 1)
{
$array[$keys[$currentIndex]] = $value;
}
else
{
if (!isset($array[$keys[$currentIndex]]))
{
$array[$keys[$currentIndex]] = array();
}
$array[$keys[$currentIndex]] = generateNew($array[$keys[$currentIndex]], $keys, $currentIndex + 1, $value);
}
return $array;
}
$result = array();
// $temp equals your original value array here...
foreach ($temp as $combinedKey => $value)
{
$result = generateNew($result, explode(".", $combinedKey), 0, $value);
}
I searched in Google and consulted the PHP documentation, but couldn't figure out how the following code works:
$some='name=Licensing Module;nextduedate=2013-04-10;status=Active|name=Test Addon;nextduedate=2013-04-11;status=Active';
function getActiveAddons($somet) {
$addons = array( );
foreach ($somet as $addon) {
if ($addon['status'] == 'Active') {
$addons[] = $addon['name'];
continue;
}
}
return $addons;
}
echo (count( getActiveAddons( $some ) ) ? implode( '<br />', getActiveAddons( $some ) ) : 'None');
The code always echo's None.
Please help me in this.
I don't know where you got this code from but you've initialized $some the wrong way. It is expected as an array like this:
$some = array(
array(
'name' => 'Licensing Module',
'nextduedate' => '2013-04-10',
'status' => 'Active'
),
array(
'name' => 'Test Addon'
'nextduedate' => '2013-04-11',
'status' => 'Active'
)
);
I guess the article you've read is expecting you to parse the original string into this format.
You can achieve this like this:
$string = 'name=Licensing Module;nextduedate=2013-04-10;status=Active|name=Test Addon;nextduedate=2013-04-11;status=Active';
$result = array();
foreach(explode('|', $string) as $record) {
$item = array();
foreach(explode(';', $record) as $column) {
$keyval = explode('=', $column);
$item[$keyval[0]] = $keyval[1];
}
$result[]= $item;
}
// now call your function
getActiveAddons($result);
$some is not an array so foreach will not operate on it. You need to do something like
$some = array(
array(
'name' => 'Licensing Module',
'nextduedate' => '2013-04-10',
'status' => 'Active'
),
array(
'name' => 'Test Addon',
'nextduedate' => '2013-04-11',
'status'=> 'Active'
)
);
This will create a multidimensional array that you can loop through.
function getActiveAddons($somet) {
$addons = array( );
foreach ($somet as $addon) {
foreach($addon as $key => $value) {
if ($key == 'status' && $value == 'Active') {
$addons[] = $addon['name'];
continue;
}
}
}
return $addons;
}
First, your $some variable is just a string. You could parse the string into an array using explode(), but it's easier to just start as an array:
$some = array(
array(
"name" => "Licensing Module",
"nextduedate" => "2013-04-10",
"status" => "Active",
),
array(
"name" => "Test Addon",
"nextduedate" => "2013-04-11",
"status" => "Active",
)
);
Now, for your function, you are on the right track, but I'll just clean it up:
function getActiveAddons($somet) {
if (!is_array($somet)) {
return false;
}
$addons = array();
foreach ($somet as $addon) {
if ($addon['status'] == 'Active') {
$addons[] = $addon['name'];
}
}
if (count($addons) > 0) {
return $addons;
}
return false;
}
And finally your output (you were calling the function twice):
$result = getActiveAddons($some);
if ($result === false) {
echo "No active addons!";
}
else {
echo implode("<br />", $result);
}
I was wondering when working with multimedional arrays, if a certain key is the same, is there a way to combine the contents of other keys into its own array if a certain key is the same?
Something like this:
// name is the same in both arrays
array(
array(
'name' => 'Pepsi',
'store' => 'Over here',
'number' => '1234567'
),
array(
'name' => 'Pepsi',
'store' => 'Over here',
'number' => '5556734'
)
)
into something like this
array(
array(
'name' => 'Pepsi',
'store' => array('Over here', 'Over here'),
'number' => array('1234567', '5556734')
)
)
The defining key is checking if the name element is the same for the other arrays.
You can try a function like this.
function mergeByKey($array,$key){
$tmp_array = array();
foreach ( $array as $k => $row ) {
$merged = false;
foreach ($tmp_array as $k2 => $tmp_row){
if ($row[$key] == $tmp_row[$key]){
foreach ( $row as $k3 => $value ) {
if ($k3 == $key) continue;
$tmp_array[$k2][$k3][] = $value;
$merged = true;
}
}
if ($merged) break;
}
if (!$merged) {
$new_row = array();
foreach ( $row as $k4 => $value ) {
if ($k4 == $key) $new_row[$k4] = $value;
else $new_row[$k4] = array($value);
}
$tmp_array[] = $new_row;
}
}
foreach ( $tmp_array as $t => $row ) {
foreach ( $row as $t2 => $value ) {
if ( count($value) == 1 && $t2 != $key ) $tmp_array[$t][$t2] = $value[0];
}
}
return $tmp_array;
}
passing the array as first parameter and the key as second one.
I'm referencing to your array structure
edited: missed a piece
edited2: if resultin array contains elements with one string, it returns a string and not a array with one element
demo
This function uses a given field name as the grouping identifier and turns all other fields into arrays.
Note that single occurrences of your field name will yield arrays with a single element for the other fields. I wasn't sure whether that's a desirable trait, but just making sure you know ;-)
$arr = array(
array(
'name' => 'Pepsi',
'store' => 'Over here',
'number' => '1234567'
),
array(
'name' => 'Pepsi',
'store' => 'Over here',
'number' => '5556734'
)
);
function mergeArray($array, $column)
{
$res = array();
foreach ($array as $item) {
foreach ($item as $key => $value) {
if ($key === $column) {
$res[$column][$key] = $value;
} else {
$res[$column][$key][] = $value;
}
}
}
return array_values($res);
}
print_r(mergeArray($arr, 'name'));
Demo
Thanks to Gianni Lovece for her answer but I was able to develop a much simpler solution based on this problem. Just plug in the $result_arr to browse through and the $key you want to use as basis and it immediately outputs a multidimensional array with non-repeating values for repeating elements (see example below).
function multiarray_merge($result_arr, $key){
foreach($result_arr as $val){
$item = $val[$key];
foreach($val as $k=>$v){
$arr[$item][$k][] = $v;
}
}
// Combine unique entries into a single array
// and non-unique entries into a single element
foreach($arr as $key=>$val){
foreach($val as $k=>$v){
$field = array_unique($v);
if(count($field) == 1){
$field = array_values($field);
$field = $field[0];
$arr[$key][$k] = $field;
} else {
$arr[$key][$k] = $field;
}
}
}
return $arr;
}
For example, in the sample array for this question, running multiarray_merge($mysample, 'name') returns
array(
'Pepsi' => array(
'name' => 'Pepsi',
'store' => 'Over here', // String: Not an array since values are not unique
'number' => array('1234567', '5556734') // Array: Saved as array since values are unique
)
);
$example =
array
'test' =>
array(
'something' => 'value'
),
'whatever' =>
array(
'something' => 'other'
),
'blah' =>
array(
'something' => 'other'
)
);
I want to count how many of $example's subarrays contain an element with the value other.
What's the easiest way to go about doing this?
array_filter() is what you need:
count(array_filter($example, function($element){
return $element['something'] == 'other';
}));
In case you want to be more flexible:
$key = 'something';
$value = 'other';
$c = count(array_filter($example, function($element) use($key, $value){
return $element[$key] == $value;
}));
You can try the following:
$count = 0;
foreach( $example as $value ) {
if( in_array("other", $value ) )
$count++;
}
This is sort of a general implementation question. If I have an arbitrarily deep array, and I do not know before hand what the keys will be, what is the best way to access the values at specific paths of the associative array? For example, given the array:
array(
'great-grandparent' = array(
'grandparent' = array(
'parent' = array(
'child' = 'value';
),
'parent2' = 'value';
),
'grandparent2' = 'value';
)
);
Whats the best way to access the value at $array['great-grandparent']['grandparent']['parent']['child'] keeping in mind that I don't know the keys beforehand. I have used eval to construct the above syntax as a string with variable names and then eval'd the string to get the data. But eval is slow and I was hoping for something faster. Something like $class->getConfigValue('great-grandparent/grandparent/'.$parent.'/child'); that would return 'value'
Example of Eval Code
public function getValue($path, $withAttributes=false) {
$path = explode('/', $path);
$rs = '$r = $this->_data[\'config\']';
foreach ($path as $attr) {
$rs .= '[\'' . $attr . '\']';
}
$rs .= ';';
$r = null;
#eval($rs);
if($withAttributes === false) {
$r = $this->_removeAttributes($r);
}
return $r;
}
I don't know about the potential speed but you don't need to use eval to do a search like that :
$conf = array(
'great-grandparent' => array(
'grandparent' => array(
'parent' => array(
'child' => 'value searched'
),
'parent2' => 'value'
),
'grandparent2' => 'value'
)
);
$path = 'great-grandparent/grandparent/parent/child';
$path = explode('/', $path);
$result = $conf;
while(count($path) > 0) {
$part = array_shift($path);
if (is_array($result) && array_key_exists($part, $result)) {
$result = $result[$part];
} else {
$result = null;
break;
}
}
echo $result;
Here we go, my solution:
$tree = array(
'great-grandparent' => array(
'grandparent' => array(
'parent' => array(
'child' => 'value1'
),
'parent2' => 'value2'
),
'grandparent2' => 'value3'
)
);
$pathParts = explode('/','great-grandparent/grandparent/parent/child');
$pathParts = array_reverse($pathParts);
echo retrieveValueForPath($tree, $pathParts);
function retrieveValueForPath($node, $pathParts) {
foreach($node as $key => $value) {
if(($key == $pathParts[count($pathParts)-1]) && (count($pathParts)==1)) {
return $value;
}
if($key == $pathParts[count($pathParts)-1]) {
array_pop($pathParts);
}
if(is_array($value)) {
$result = retrieveValueForPath($value, $pathParts);
}
}
return $result;
}