Convert array index in a custom string layout? - php

I have an array called $context with this structure:
array(2) {
[0]=>
array(2) {
["name"]=>
string(6) "Foo"
["username"]=>
string(6) "Test"
}
[1]=>
array(2) {
["name"]=>
string(4) "John"
["username"]=>
string(3) "Doe"
}
}
I want convert it into this string:
string 1:
0: array(
'name' => 'Foo',
'username' => 'Test',
)
string 2:
1: array(
'name' => 'John',
'username' => 'Doe',
)
How you can see I want save the current index in the iteration and display the array content formatted as 'name' and 'username' in a single line. I already tried with this code:
$export = '';
foreach($context as $key => $value)
{
$export .= "{$key}: ";
print_r($value);
$export .= preg_replace(array(
'/=>\s+([a-zA-Z])/im',
'/array\(\s+\)/im',
'/^ |\G /m'
), array(
'=> $1',
'array()',
' '
), str_replace('array (', 'array(', var_export($value, true)));
print_r($export);
$export .= PHP_EOL;
}
return str_replace(array('\\\\', '\\\''), array('\\', '\''), rtrim($export));
but I'm looking for a more optimized solution, any suggest?

This is my code:
$context = [['name'=>'Foo','username'=>'Test'],['name'=>'John','username'=>'Doe']];
$schema = " '%s' => '%s'";
$lineBreak = PHP_EOL;
foreach( $context as $idx => $array )
{
$lines = array();
foreach( $array as $key => $val )
{
$lines[] = sprintf( $schema, $key, $val );
}
$output = "{$idx}: array({$lineBreak}".implode( ",{$lineBreak}", $lines )."{$lineBreak})";
echo $output.$lineBreak;
}
3v4l.org demo
It will works independently from the number of elements in sub-arrays
I have used classic built-in function sprintf to format each array row: see more.
You can change $lineBreak with you preferred endLine character;
In the above example, each string is printed, but (you have a return in your function, so i think inside a function), you can modify in this way:
$output = array();
foreach( $context as $idx => $array )
{
(...)
$output[] = "{$idx}: array({$lineBreak}".implode( ",{$lineBreak}", $lines )."{$lineBreak})";
}
to have an array filled with formatted string.
You can easly transform it in a function:
function contextToString( $context, $schema=Null, $lineBreak=PHP_EOL )
{
if( !$schema ) $schema = " '%s' => '%s'";
$output = array();
foreach( $context as $idx => $array )
{
$lines = array();
foreach( $array as $key => $val )
{
$lines[] = sprintf( $schema, $key, $val );
}
$output[] = "{$idx}: array({$lineBreak}".implode( ",{$lineBreak}", $lines )."{$lineBreak})";
}
return implode( $lineBreak, $output );
}
to change each time the schema and the line break.
PS: I see that in you code there is a comma also at the end of the last element of eache array; thinking it was a typo, I have omitted it
Edit: I have forgot the comma, added-it.
Edit 2: Added complete function example.
Edit 3: Added link to sprintf PHP page

Try this with personnal toString
$a = array(array("name"=>"Foo", "username"=>"Test"), array("name"=>"John", "username"=>"Doe"));
function toString($array){
$s = ""; $i=0;
foreach ($array as $key => $value) {
$s.= $key."=>".$value;
if($i < count($array)-1)
$s.=",";
$i++;
}
return $s;
}
$result = array();
$index = 0;
foreach ($a as $value) {
array_push($result, $index. " : array(" . toString($value).")");
$index ++;
}
var_dump($result);
And the result :
array (size=2)
0 => string '0 : array(name=>Foo,username=>Test)' (length=35)
1 => string '1 : array(name=>John,username=>Doe)' (length=35)
The result is in an array but you can change and make what you want
But you can also use json_encode :
$result = array();
$index = 0;
foreach ($a as $value) {
array_push($result, $index. " : array(" . json_encode($value).")");
$index ++;
}
var_dump($result);
With this result :
array (size=2)
0 => string '0 : array({"name":"Foo","username":"Test"})' (length=43)
1 => string '1 : array({"name":"John","username":"Doe"})' (length=43)

Simplified solution with strrpos,substr_replace and var_export:
$arr = [
array(
'name' => 'John',
'username' => 'Doe'
),
array(
'name' => 'Mike',
'username' => 'Tyson'
)
];
/*****************/
$strings = [];
foreach($arr as $k => $v){
$dump = var_export($v, true);
$last_comma_pos = strrpos($dump,",");
$cleared_value = substr_replace($dump, "", $last_comma_pos, 1);
$strings[] = $k.": ".$cleared_value;
}
/*****************/
// Now $strings variable contains all the needed strings
echo "<pre>";
foreach($strings as $str){
echo $str . "\n";
}
// the output:
0: array (
'name' => 'John',
'username' => 'Doe'
)
1: array (
'name' => 'Mike',
'username' => 'Tyson'
)

Related

Array to comma separated string?

My php code is
public function getAllAttributes()
{
$this->dao->select('b_title');
$this->dao->from($this->getTable_buttonsAttr());
$result = $this->dao->get();
if( !$result ) {
return array() ;
}
return $result->result();
}
$details = Modelbuttons::newInstance()->getAllAttributes();
$string = implode(', ', $details);
var_dump ($string) ; ?>
I get this an array that looks like this:
array (size=6)
0 =>
array (size=1)
'b_title' => string 'test 10' (length=12)
1 =>
array (size=1)
'b_title' => string 'test 11' (length=12)
2 =>
array (size=1)
'b_title' => string 'test 12' (length=13)
3 =>
array (size=1)
'b_title' => string 'test 13' (length=8)
4 =>
array (size=1)
'b_title' => string 'test 14' (length=14)
5 =>
array (size=1)
'b_title' => string 'test 15' (length=32)
How can I transform this array to a string like this with PHP?
$out = '10, 11, 12, 13, 14,15';
You can try this code.
$array = [['b_title' => 'test 10'],['b_title' => 'test 11']];
foreach($array as $a) {
$values[] = explode(' ', $a['b_title'])[1];
}
echo implode(', ', $values);
Basic Example:
<?php
// your array
$array = array(
array('b_title'=>'test 10'),
array('b_title'=>'test 11'),
array('b_title'=>'test 12'),
array('b_title'=>'test 13')
);
$newArr = array();
foreach ($array as $key => $value) {
$newVal = explode(" ", $value['b_title']);
$newArr[] = $newVal[1];
}
echo implode(',', $newArr); // 10,11,12,13
?>
Explanation:
First of all use explode() for your string value which help you to Split a string as required:
$newVal = explode(" ", $value['b_title']);
Than you can store index 1 in an array as:
$newArr[] = $newVal[1]; // array(10,11,12,13)
In last, you just need to use implode() function which help you to get comma separated data.
echo implode(',', $newArr); // 10,11,12,13
An alternative way to do.
$details = Modelbuttons::newInstance()->getAllAttributes(); /*[['b_title' => 'test 10'],['b_title' => 'test 11']];*/
$token = "";
foreach($details as $row1){
$token = $token.$row1['b_title'].", ";
}
echo rtrim(trim($token),",");
Output: test 10, test 11
Explanation
Through foreach, all array values are now comma separated.
As of now, output will be test 10, test 11,. So, remove extra comma which trail in the end through rtrim().
There are many ways to skin this cat -- Here's one:
<?php
$out = '';
foreach ($array as $arrayItem) {
$out .= $arrayItem['b_title'] . ', ';
}
// Remove the extraneous ", " from the $out string.
$out = substr($out, 0, -2);
?>
Or if you were also wanting to remove the "test " portion of the 'b_title' key's value; then you could accomplish it like so:
<?php
$out = '';
foreach ($array as $arrayItem) {
$out .= str_replace('test ', '', $arrayItem['b_title']) . ', ';
}
// Remove the extraneous ", " from the $out string.
$out = substr($out, 0, -2);
?>
// Construct a new array of the stripped numbers
$flattenedArray = array_map(function($item) {
list(, $number) = explode(' ', $item['b_title']);
return $number;
}, $yourArray);
// Concatenate the numbers into a string joined by ,
$out = implode(', ', $flattenedArray);
This gives the result you want. It could do with a few conditions in there though to check arrays are in the correct format before manipulation etc.
You can try this also
$check = array(array ('b_title' => array('test 10'))
,array('b_title' => array('test 11'))
,array('b_title' => array('test 12'))
,array('b_title' => array('test 13'))
,array('b_title' => array('test 14'))
,array('b_title' => array('test 15')));
$srt = "";
foreach($check as $kye => $val)
{
$title = $val['b_title'][0];
$var = explode(' ',$title);
$srt .= trim($var[1]).', ';
}
$srt = substr(trim($srt),0,-1);
$test_array = array(
0 => array('b_title' => 'test 10'),
1 => array('b_title' => 'test 11'),
2 => array('b_title' => 'test 12'),
3 => array('b_title' => 'test 13'),
4 => array('b_title' => 'test 14'),
5 => array('b_title' => 'test 15'),
);
$result = "";
$result1 = array_walk($test_array, function ($value, $key) use(&$result) {
$result .= ",".array_pop(explode(" ", reset($value))).",";
$result = trim($result, ",");
});
Output: $out = '10, 11, 12, 13, 14,15';
Explanation
Iterate over array by using PHP's native array_walk() which will reduce forloops and then prepare array by using explode(),array_pop() and trim() which is likely required to prepare your required string.
Try this,
foreach($test_array as $val)
{
$new_array[] = preg_replace('/\D/', '', $val['b_title']);
}
$out = implode(',', $new_array);
echo $out;
OUTPUT
10,11,12,13,14,15
DEMO
You can use on mentioned URL solution Click here
foreach ($arr as $k=>$val) {
$v = explode (' ', $val['b_title']);
$out .= $v[1].',';
}
$out = rtrim ($out, ',');
echo '<pre>'; print_r($out); die;

Output multidimensional array to list

Can anyone help output a multidimensional array, please.
Not to sure where I have gone wrong.
The sort ordering looks correct, but its not displaying the results.
<?php
$atest = Array ( "0" => Array ( "id" => "913", "testname" => "qwerty1", "i" => "1" ),
"1" => Array ( "id" => "913", "testname" => "test22", "i" => "2" ),
"2" => Array ( "id" => "913", "testname" => "American1", "i" => "3" ),
"3" => Array ( "id" => "913", "testname" => "Eagle4", "i" => "4" ) );
$range = range('A','Z');
$output = array();
$output['#'] = array();
foreach($range as $letter){
$output[$letter] = array();
}
foreach($atest as $test){
if ($test["testname"] !='') {
$uc = ucfirst($test["testname"]);
if(array_search($uc[0], $range) === FALSE){
$output['#'][] = $uc;
} else {
$output[$uc[0]][] = $uc;
}
}
}
foreach($output AS $letter => $result){
echo $letter . "<br/>--------<br/>\n";
sort($result);
foreach($result AS $indresult){
echo '' . $indresult['testname'] . '<br/>';
}
echo "<br/>\n";
}
?>
You're not putting the whole sub-array into $output, you're only putting $uc. Change the middle foreach loop to:
foreach($atest as $test){
if ($test["testname"] !='') {
$uc = ucfirst($test["testname"]);
if(array_search($uc[0], $range) === FALSE){
$output['#'][] = $test;
} else {
$output[$uc[0]][] = $test;
}
}
}
Try to use print_r function, for example for array dump:
print_r($atest);
Try this
$output[$uc[0]][] = $test;
instead of
$output[$uc[0]][] = $uc; // only the name is stored.
See demo here

Read nested array dynamicly in php

I need to read nested arrays without knowing how the array will look.
For example;
$data = array(
'Data1_lvl1' => array(
'Data1_lvl2' => "value",
'Data2_lvl2' => array(
'Data1_lvl3' => "value"
)
),
'Data2_lvl1' => 'value'
);
Needs to be formatted to strings like:
Data1_lvl1/Data1_lvl2/
Data1_lvl1/Data2_lvl2/Data1_lvl3/
Data2_lvl1/
But the array can be of any size with any number of nested arrays inside it.
$data = array(
'Data1_lvl1' => array(
'Data1_lvl2' => "value",
'Data2_lvl2' => array(
'Data1_lvl3' => "value"
)
),
'Data2_lvl1' => 'value'
);
function printArray($array)
{
foreach ($array as $key=>$value)
{
echo $key.'/';
if (is_array($value))
{
printArray($value);
} else {
echo '<br>';
}
}
}
printArray($data);
If you want to output only the name of array elements then this recursive function will do the trick.
Your data:
$data = array(
'Data1_lvl1' => array(
'Data1_lvl2' => "value",
'Data2_lvl2' => array(
'Data1_lvl3' => "value"
)
),
'Data2_lvl1' => 'value'
);
Function:
function array2str($array, $str) {
foreach($array as $key => $val) {
if (is_array($val) ) {
$str .= $key . '/';
array2str($val, $str);
}
}
echo $str.'<br />';
return $str;
}
array2str($data);
As you can see the script does ECHO in itself with <br /> to break the line when viewing results in a browser.
One way would to walk recursively through array with function similar to this:
<?php
function f($d, $str = '') {
foreach ($d as $key => $val) {
if (is_array($val)) f($val, $str . '/' . $key); // If this element is array parse next level
else print_r($str . '/' . $key . '/'); // Output current string or do what you need to do with it..
}
}
$data = array(
'Data1_lvl1' => array(
'Data1_lvl2' => "value",
'Data2_lvl2' => array(
'Data1_lvl3' => "value"
)
),
'Data2_lvl1' => 'value'
);
f($data);
with that function:
<?php
function print_tree ($data, $prefix = '', &$index = 1) {
foreach($data as $key => $datum) {
echo $index++ . '. ' . ($new_prefix = $prefix . $key . '/') . PHP_EOL;
if (is_array($datum)) {
print_tree ($datum, $new_prefix, $index);
}
}
}
I get
Data1_lvl1/
Data1_lvl1/Data1_lvl2/
Data1_lvl1/Data2_lvl2/
Data1_lvl1/Data2_lvl2/Data1_lvl3/
Data2_lvl1/

most efficient method of turning multiple 1D arrays into columns of a 2D array

As I was writing a for loop earlier today, I thought that there must be a neater way of doing this... so I figured I'd ask. I looked briefly for a duplicate question but didn't see anything obvious.
The Problem:
Given N arrays of length M, turn them into a M-row by N-column 2D array
Example:
$id = [1,5,2,8,6]
$name = [a,b,c,d,e]
$result = [[1,a],
[5,b],
[2,c],
[8,d],
[6,e]]
My Solution:
Pretty straight forward and probably not optimal, but it does work:
<?php
// $row is returned from a DB query
// $row['<var>'] is a comma separated string of values
$categories = array();
$ids = explode(",", $row['ids']);
$names = explode(",", $row['names']);
$titles = explode(",", $row['titles']);
for($i = 0; $i < count($ids); $i++) {
$categories[] = array("id" => $ids[$i],
"name" => $names[$i],
"title" => $titles[$i]);
}
?>
note: I didn't put the name => value bit in the spec, but it'd be awesome if there was some way to keep that as well.
Maybe this? Not sure if it's more efficient but it's definitely cleaner.
/*
Using the below data:
$row['ids'] = '1,2,3';
$row['names'] = 'a,b,c';
$row['titles'] = 'title1,title2,title3';
*/
$categories = array_map(NULL,
explode(',', $row['ids']),
explode(',', $row['names']),
explode(',', $row['titles'])
);
// If you must retain keys then use instead:
$withKeys = array();
foreach ($row as $k => $v) {
$v = explode(',', $v);
foreach ($v as $k2 => $v2) {
$withKeys[$k2][$k] = $v[$k2];
}
}
print_r($categories);
print_r($withKeys);
/*
$categories:
array
0 =>
array
0 => int 1
1 => string 'a' (length=1)
2 => string 'title1' (length=6)
...
$withKeys:
array
0 =>
array
'ids' => int 1
'names' => string 'a' (length=1)
'titles' => string 'title1' (length=6)
...
*/
Just did a quick simple benchmark for the 4 results on this page and got the following:
// Using the following data set:
$row = array(
'ids' => '1,2,3,4,5',
'names' => 'abc,def,ghi,jkl,mno',
'titles' => 'pqrs,tuvw,xyzA,BCDE,FGHI'
);
/*
For 10,000 iterations,
Merge, for:
0.52803611755371
Merge, func:
0.94854116439819
Merge, array_map:
0.30260396003723
Merge, foreach:
0.40261697769165
*/
Yup, array_combine()
$result = array_combine( $id, $name );
EDIT
Here's how I'd handle your data transformation
function convertRow( $row )
{
$length = null;
$keys = array();
foreach ( $row as $key => $value )
{
$row[$key] = explode( ',', $value );
if ( !is_null( $length ) && $length != count( $row[$key] ) )
{
throw new Exception( 'Lengths don not match' );
}
$length = count( $row[$key] );
// Cheap way to produce a singular - might break on some words
$keys[$key] = preg_replace( "/s$/", '', $key );
}
$output = array();
for ( $i = 0; $i < $length; $i++ )
{
foreach ( $keys as $key => $singular )
{
$output[$i][$singular] = $row[$key][$i];
}
}
return $output;
}
And a test
$row = convertRow( $row );
echo '<pre>';
print_r( $row );

Get array's key recursively and create underscore separated string

Right now i got an array which has some sort of information and i need to create a table from it. e.g.
Student{
[Address]{
[StreetAddress] =>"Some Street"
[StreetName] => "Some Name"
}
[Marks1] => 100
[Marks2] => 50
}
Now I want to create database table like which contain the fields name as :
Student_Address_StreetAddress
Student_Address_StreetName
Student_Marks1
Student_Marks2
It should be recursive so from any depth of array it can create the string in my format.
You can use the RecursiveArrayIterator and the RecursiveIteratorIterator (to iterate over the array recursively) from the Standard PHP Library (SPL) to make this job relatively painless.
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
$keys = array();
foreach ($iterator as $key => $value) {
// Build long key name based on parent keys
for ($i = $iterator->getDepth() - 1; $i >= 0; $i--) {
$key = $iterator->getSubIterator($i)->key() . '_' . $key;
}
$keys[] = $key;
}
var_export($keys);
The above example outputs something like:
array (
0 => 'Student_Address_StreetAddress',
1 => 'Student_Address_StreetName',
2 => 'Student_Marks1',
3 => 'Student_Marks2',
)
(Working on it, here is the array to save the trouble):
$arr = array
(
'Student' => array
(
'Address' => array
(
'StreetAddress' => 'Some Street',
'StreetName' => 'Some Name',
),
'Marks1' => '100',
'Marks2' => '50',
),
);
Here it is, using a modified version of #polygenelubricants code:
function dfs($array, $parent = null)
{
static $result = array();
if (is_array($array) * count($array) > 0)
{
foreach ($array as $key => $value)
{
dfs($value, $parent . '_' . $key);
}
}
else
{
$result[] = ltrim($parent, '_');
}
return $result;
}
echo '<pre>';
print_r(dfs($arr));
echo '</pre>';
Outputs:
Array
(
[0] => Student_Address_StreetAddress
[1] => Student_Address_StreetName
[2] => Student_Marks1
[3] => Student_Marks2
)
Something like this maybe?
$schema = array(
'Student' => array(
'Address' => array(
'StreetAddresss' => "Some Street",
'StreetName' => "Some Name",
),
'Marks1' => 100,
'Marks2' => 50,
),
);
$result = array();
function walk($value, $key, $memo = "") {
global $result;
if(is_array($value)) {
$memo .= $key . '_';
array_walk($value, 'walk', $memo);
} else {
$result[] = $memo . $key;
}
}
array_walk($schema, 'walk');
var_dump($result);
I know globals are bad, but can't think of anything better now.
Something like this works:
<?php
$arr = array (
'Student' => array (
'Address' => array (
'StreetAddress' => 'Some Street',
'StreetName' => 'Some Name',
),
'Marks1' => array(),
'Marks2' => '50',
),
);
$result = array();
function dfs($data, $prefix = "") {
global $result;
if (is_array($data) && !empty($data)) {
foreach ($data as $key => $value) {
dfs($value, "{$prefix}_{$key}");
}
} else {
$result[substr($prefix, 1)] = $data;
}
}
dfs($arr);
var_dump($result);
?>
This prints:
array(4) {
["Student_Address_StreetAddress"] => string(11) "Some Street"
["Student_Address_StreetName"] => string(9) "Some Name"
["Student_Marks1"] => array(0) {}
["Student_Marks2"] => string(2) "50"
}
function getValues($dataArray,$strKey="")
{
global $arrFinalValues;
if(is_array($dataArray))
{
$currentKey = $strKey;
foreach($dataArray as $key => $val)
{
if(is_array($val) && !empty($val))
{
getValues($val,$currentKey.$key."_");
}
else if(!empty($val))
{
if(!empty($strKey))
$strTmpKey = $strKey.$key;
else
$strTmpKey = $key;
$arrFinalValues[$strTmpKey]=$val;
}
}
}
}

Categories