I'm trying to replicate Facebook's nested request syntax in PHP, converting the fields parameter into a multidimensional array.
/me?fields=name,updated_time,photos{name,source},likes{name,link},events.limit(4){name,start_time,end_time,photos}
Would result in something along the lines of...
Array
(
[name]
[updated_time]
[photos] => Array
(
[name]
[source]
)
[likes] => Array
(
[name]
[link]
)
)
Figured out how to match the graph API Using a loop. Decided it would be best to keep the filter, and limit modifiers as part of the object in order to keep the array as clean as possible
$a = $input;
$output = array();
$outputStacktrace = array(&$output);
$depth = 0;
$buffer = $key = '';
$m = memory_get_usage();
for ($i = 0; $i < strlen($a); $i++)
if ($a[$i] == ',') {
if (strlen($buffer))
if($depth == 0){
if(is_array($outputStacktrace[0]) && empty($outputStacktrace[0])){
$outputStacktrace[$depth][$buffer] = array();
}
} else {
$outputStacktrace[$depth][$key ? $key : count($outputStacktrace[$depth])] = $buffer;
}
$buffer = $key = '';
} elseif ($a[$i] == '{') {
$outputStacktrace[$depth][$buffer] = array();
$outputStacktrace[$depth + 1] = &$outputStacktrace[$depth][$buffer];
$depth++;
$buffer = '';
} elseif ($a[$i] == '}') {
if (strlen($buffer))
$outputStacktrace[$depth][$key ? $key : count($outputStacktrace[$depth])] = $buffer;
$buffer = $key = '';
unset($outputStacktrace[$depth]);
$depth--;
} else {
$buffer .= $a[$i];
}
if( $buffer!='' )
$outputStacktrace[$depth][$key ? $key : count($outputStacktrace[$depth])] = $buffer;
return ($output);
Related
Help!
I want to make this part of code shorter and more transformative. My $named array looks like:
Array
(
[0] => Array
(
[0] => Array
(
[0] => Header
)
[1] => Array
(
[0] => some text
[1] => some text
)
)
[1] => Array
(
[0] => Array
(
[0] => Header
)
[1] => Array
(
[0] =>
[1] => some text
)
[2] => Array
(
[0] => some text
)
)
)
So, I would like to save to a new csv file if the number of "header" exceeds 100. How can I open and close a file with the correct index without having to manually type "/named_1" or "/named_2"? At the moment I have a y variable that goes through the $named array and writes to the file until there are 100 headers. How can I not repeat the code?
Also each line must have a total of 38 semicolons.
$file = fopen(__DIR__ . '/named_1.csv', 'w');
$file_2 = fopen(__DIR__ . '/named_2.csv', 'w');
$file_3 = fopen(__DIR__ . '/named_3.csv', 'w');
$y=0;
foreach ($named as $array) {
foreach($array as $row){
if($y < 100){
$line = '';
for ($i=0; $i <= 38; $i++) {
if (count($row) > $i) {
$line .= $row[$i];
($i != 38 ? $line .= ';' : '');
} else {
($i != 38 ? $line .= ';' : '');
}
}
fwrite($file, $line.PHP_EOL);
}
if($y > 99 && $y <200){
$line = '';
for ($i=0; $i <= 38; $i++) {
if (count($row) > $i) {
$line .= $row[$i];
($i != 38 ? $line .= ';' : '');
} else {
($i != 38 ? $line .= ';' : '');
}
}
fwrite($file_2, $line.PHP_EOL);
}
if($y > 199 && $y <300){
$line = '';
for ($i=0; $i <= 38; $i++) {
if (count($row) > $i) {
$line .= $row[$i];
($i != 38 ? $line .= ';' : '');
} else {
($i != 38 ? $line .= ';' : '');
}
}
fwrite($file_3, $line.PHP_EOL);
}
}
$y++;
}
fclose($file);
touch( __DIR__ . '/named_1.csv');
fclose($file_2);
touch( __DIR__ . '/named_2.csv');
fclose($file_3);
touch( __DIR__ . '/named_3.csv');
Please try the following code. I added a function for composing filename for different needs.
function composeFilename($k, $mod, $type=1)
{
switch($type)
{
// for named_1-100.csv, named_101-200.csv, ...
case 1:
$from = $k - $mod + 2;
$to = $k+1;
$suffix = $from . "_" .$to;
break;
// for named_0-99.csv, named_100-199.csv, ...
case 2:
$from = $k - $mod + 1;
$to = $k;
$suffix = $from . "_" .$to;
break;
// for named_1.csv, named_2.csv, ...
default:
$suffix = ($k % $mod)+1;
}
return "named_$suffix.csv";
}
$lines = [];
$mod = 100;// The max number of rows in each output file
$outputDirectory = __DIR__ . "/";
$lastIndex = count($named) - 1;
foreach ($named as $k => $array){
foreach($array as $row){
$lines[] = trim(implode(";", $row));
}
// Write output file for every $mod lines or for the rest
if(($k+1) % $mod == 0 || $k == $lastIndex){
$filename = $outputDirectory . composeFilename($k, $mod);
if(file_put_contents($filename, implode(PHP_EOL, $lines))){
// Reset lines array for the next chunk
$lines = [];
}
else {
die("$filename could not be saved.");
}
}
}
Example string: "outofthebox"
I want to get output like this: Array ( [0] => out [1] => of [2] => the [3] => box )
What do I get right now: Array ( [0] => out [1] => oft [2] => heb [3] => ox )
I don't know how it's possible. I need that logic, how can I get more meaningful results.
I'm building it on PHP based on this https://stackoverflow.com/a/481773/17035224 Python answer. But I'm not good at Python. In this python script it's returning results like exactly what I want. Another script in python called 'wordninja' is working great too.
My PHP script:
<?php
$db = new PDO("mysql:host=localhost;dbname=strings", "root", "");
$text = "outofthebox";
$finish = false;
$words = [];
$find = false;
$start = -1;
$added = false;
$comp = [];
for($i = 0; $i<strlen($text); $i++) {
if(count($words) > 0) {
$last = max($words);
$comp[] = $last;
$words = [];
$start = strlen(implode("", $comp));
if($added === true) {
$added = false;
}else {
$start++;
}
}else {
$start++;
}
$part = "";
for($j = $start; $j<strlen($text); $j++) {
$part .= $text[$j];
echo $part."<br>";
$check = checkWord($part);
if($check === true) {
$added = true;
$words[] = $part;
}
}
}
print_r($comp);
function checkWord($text) {
global $db;
$check = $db->query("select * from strings where string='".$text."'")->fetch(PDO::FETCH_ASSOC);
if(isset($check["id"]) == true) {
return true;
}
return false;
}
Other difference is as you see I'm using mysql database for dictionary instead of txt.
If you change the checkWord function to this :
function checkWord($text) {
$arr = [
'out',
'of',
'the',
'box',
];
if(in_array($text, $arr)) {
return true;
}
return false;
}
You will see that the result will be :
Array ( [0] => out [1] => of [2] => the [3] => box )
So my guess is that you have false-positives coming from your query, check that and you'll solve the problem.
I have dynamic multidimensional array that contain directory, sub-directory and file names in a project folder, key indicating a sub-directory name and value indicating file names, if a key equal to number indicating only file and then if a key hasn't any value indicating there is no file at all in a directory. The array look like this :
Array
(
[0] => index.php
[src] => Array
(
[src2] => Array
(
[src3] => Array
(
[0] => test_src3.php
)
[0] => Array
(
[0] => test_src2.php
)
)
[0] => test_src.php
)
[src_test] => Array
(
[New Folder] => Array
(
)
[src_test2] => Array
(
[New Folder] => Array
(
)
[src_test3] => Array
(
)
)
)
[1] => test.php
)
The number of dimensions might be change based on sub directories that found in a folder path inputted by user (this program is used by a person in their local).
How could i fetch those array elements so that the result would be like this :
array(
[0] => src/src2/src3/
[1] => src_test/New Folder/
[2] => src_test/src_test2/New Folder/
[3] => src_test/src_test2/src_test3/
)
By the way i have a function to achieve this :
<?php
// Get specific element where the first index is 1 instead of 0
function getAtPos($tmpArray,$pos) {
$keys = array_keys($tmpArray);
return array($keys[$pos-1] => $tmpArray[$keys[$pos-1]]);
}
// Get all Keys that has String type only
function getKeyStr(array $mixed, $numbIdx){
$results = [];
$tmp = array_keys($mixed);
$ii = 0;
for ($i=1; $i <= $numbIdx; $i++) {
$keyArr = getAtPos($tmp, $i);
if (is_string($keyArr[$ii])) {
$results[] = $keyArr[$ii];
}
$ii++;
}
return $results;
}
function getKeyPaths(array $tree, $glue = '/', $return_array = true){
$paths = "";
$result = [];
foreach ($tree as $key => &$mixed) {
if (is_array($mixed) && !is_int($key)) {
$path = $key . $glue;
$retArrFalse = false;
$jlhMixed = count($mixed);
$getKeyStr = getKeyStr($mixed, $jlhMixed);
$jlhKeyStr = count($getKeyStr);
if ($jlhKeyStr < 2) {
$repeat = getKeyPaths($mixed, $glue, $retArrFalse);
$paths .= $path . $repeat;
if ($return_array) {
$paths .= "|";
}
}elseif($jlhKeyStr > 1) {
for ($i=0; $i < $jlhKeyStr; $i++) {
$idxAsso = $getKeyStr[$i];
$jlhKeySub = count($mixed[$idxAsso]);
$path2 = $idxAsso . $glue;
if ($jlhKeySub > 0) {
$paths .= $path . $path2 . getKeyPaths($mixed[$idxAsso], $glue, $retArrFalse);
if ($return_array) {
$paths .= "|";
}
}else{
$paths .= $path . $path2;
if ($return_array) {
$paths .= "|";
}
} // END of if else
} // END of for loop
} // END of elseif
}
} // END of foreach
if ($return_array) {
return explode("|", trim($paths, "|"));
}
return $paths;
}
the above function does not result like what i expected:
Array
(
[0] => src/src2/src3/
[1] => src_test/New Folder/
[2] => src_test/src_test2/New Folder/src_test3/
)
How do i achieve this ?
Any help would be appreciated !
UPDATE
I have modified my function trying to solve this:
<?php
// To get spesific element on dynamic associative array
function getAtPos($tmpArray,$pos) { // $pos is an index order starting with 1 instead of 0
$keys = array_keys($tmpArray);
return array($keys[$pos-1] => $tmpArray[$keys[$pos-1]]);
}
// Get key string type (associative) only in the given array
function getKeyStr(array $mixed, $numbIdx){
$results = [];
$tmp = array_keys($mixed); // change key to element (as array number).
$ii = 0;
for ($i=1; $i <= $numbIdx; $i++) {
$keyArr = getAtPos($tmp, $i);
if (is_string($keyArr[$ii])) {
$results[] = $keyArr[$ii];
}
$ii++;
}
return $results; // Return all second dimension sub-keys of the given array (parent)
}
// EDITED !
function getKeyPaths2(array $tree, $glue = '/', $return_array = true, $goToIfElse = false, $saveSameParent = []){
$paths = "";
$result = [];
$iFor = 0;
foreach ($tree as $key => &$mixed) {
if (is_array($mixed) && !is_int($key)) {
$path = $key . $glue;
$retArrFalse = false;
$jlhMixed = count($mixed);
$getKeyStr = getKeyStr($mixed, $jlhMixed); // Contain sub-keys of the second dimension of the parent
$jlhKeyStr = count($getKeyStr); // Count number of sub-keys of second dimension of parent
if ($goToIfElse !== false) {
$jlhKeyStr = $goToIfElse;
$iFor++;
unset($mixed);
$mixed = $tree;
$jlhMixed = count($mixed);
$getKeyStr = getKeyStr($mixed, $jlhMixed); // Contain sub-keys of the second dimension of the
$jlhKeyStr = count($getKeyStr); // Count number of sub-keys of second dimension of parent
}
if ($jlhKeyStr < 2) {
$repeat = getKeyPaths2($mixed, $glue, $retArrFalse);
$paths .= $path . $repeat;
if (!$return_array && $jlhKeyStr < 1) {
$paths .= "|";
}
}elseif($jlhKeyStr > 1) {
for ($i=$iFor; $i < $jlhKeyStr; $i++) {
$idxAsso = $getKeyStr[$i];
$jlhKeySub = count($mixed[$idxAsso]);
$path2 = $idxAsso . $glue;
if ($jlhKeySub > 0) {
$paths .= $path . $path2;
// TEST
$pecah = explode("|", $paths);
$saveSameParent[0] = end($pecah);
if ($return_array) {
$paths .= "|";
}
$paths .= $path . $path2 . getKeyPaths2($mixed[$idxAsso], $glue, $retArrFalse, $jlhKeyStr, $saveSameParent);
if ($return_array) {
$paths .= "|";
}
}else{
if ($goToIfElse !== false) {
$paths .= $path;
$paths .= "|";
$paths .= $saveSameParent[0] . $path2;
$paths .= "|";
}else{
$paths .= $path . $path2;
}
if ($return_array || $goToIfElse !== false) {
$paths .= "|";
}
} // END of if else
} // END of for loop
} // END of elseif
}
} // END of foreach
if ($return_array) {
return explode("|", trim($paths, "|"));
}
return $paths;
}
But this only works with my example array that i showed above.
If the given array like this, this would not work:
<?php
$tree = [];
$tree[0] = "index.php";
$tree["src"]["src2"]["src3"][0] = "test_src3.php";
$tree["src"]["src2"][0][0] = "test_src2.php";
$tree["src"][0] = "test_src.php";
$tree["src_test"]["New Folder"] = array();
$tree["src_test"]["src_test2"]["New Folder"] = array();
$tree["src_test"]["src_test2"]["src_test3.1"] = array();
$tree["src_test"]["src_test2"]["src_test3.2"] = array();
$tree["src_test"]["src_test2"]["src_test3.1"]["src_test3.1.1"] = array();
$tree["src_test"]["src_test2"]["src_test3.2"]["src_test3.2.1"]["src_test3.2.2"]["src_test3.2.3"] = array("test_src4.php", "test_src5.php");
The result would be :
Array
(
[0] => src/src2/src3/
[1] => src_test/New Folder/
[2] => src_test/src_test2/
[3] => src_test/src_test2/New Folder/src_test3.1/New Folder/src_test3.1/src_test3.1.1/src_test3.1.1/
[4] => New Folder/src_test3.2/New Folder/src_test3.2/src_test3.2.1/src_test3.2.1/src_test3.2.2/src_test3.2.3/
[5] => src_test3.1/src_test3.2/src_test3.1/src_test3.2/src_test3.2.1/src_test3.2.1/src_test3.2.2/src_test3.2.3/
)
I have text which is generated by print_r($some_array,true) and it looks something like this:
Array
(
[name] => Jon
[lastname] => Jonson
[car] => Array
(
[name] => bmw
[year] => 2012
)
)
(Real data have much more values and more dimensions.)
Question: how to convert this data back, into php's array ?
Looking at the print_r documentation on php.net 'Matt' has posted a solution:
<?php
function print_r_reverse($in) {
$lines = explode("\n", trim($in));
if (trim($lines[0]) != 'Array') {
// bottomed out to something that isn't an array
return $in;
} else {
// this is an array, lets parse it
if (preg_match("/(\s{5,})\(/", $lines[1], $match)) {
// this is a tested array/recursive call to this function
// take a set of spaces off the beginning
$spaces = $match[1];
$spaces_length = strlen($spaces);
$lines_total = count($lines);
for ($i = 0; $i < $lines_total; $i++) {
if (substr($lines[$i], 0, $spaces_length) == $spaces) {
$lines[$i] = substr($lines[$i], $spaces_length);
}
}
}
array_shift($lines); // Array
array_shift($lines); // (
array_pop($lines); // )
$in = implode("\n", $lines);
// make sure we only match stuff with 4 preceding spaces (stuff for this array and not a nested one)
preg_match_all("/^\s{4}\[(.+?)\] \=\> /m", $in, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
$pos = array();
$previous_key = '';
$in_length = strlen($in);
// store the following in $pos:
// array with key = key of the parsed array's item
// value = array(start position in $in, $end position in $in)
foreach ($matches as $match) {
$key = $match[1][0];
$start = $match[0][1] + strlen($match[0][0]);
$pos[$key] = array($start, $in_length);
if ($previous_key != '') $pos[$previous_key][1] = $match[0][1] - 1;
$previous_key = $key;
}
$ret = array();
foreach ($pos as $key => $where) {
// recursively see if the parsed out value is an array too
$ret[$key] = print_r_reverse(substr($in, $where[0], $where[1] - $where[0]));
}
return $ret;
}
}
?>
(Not my code)
I have some data in this format:
even--heaped<br />
even--trees<br />
hardrocks-cocked<br />
pebble-temple<br />
heaped-feast<br />
trees-feast<br />
and I want to end up with an output so that all lines with the same words get added to each other with no repeats.
even--heaped--trees--feast<br />
hardrocks--cocked<br />
pebbles-temple<br />
i tried a loop going through both arrays but its not the exact result I want. for an array $thing:
Array ( [0] => even--heaped [1] => even--trees [2] => hardrocks--cocked [3] => pebbles--temple [4] => heaped--feast [5] => trees--feast )
for ($i=0;$i<count($thing);$i++){
for ($j=$i+1;$j<count($thing);$j++){
$first = explode("--",$thing[$i]);
$second = explode("--",$thing[$j]);
$merge = array_merge($first,$second);
$unique = array_unique($merge);
if (count($unique)==3){
$fix = implode("--",$unique);
$out[$i] = $thing[$i]."--".$thing[$j];
}
}
}
print_r($out);
but the result is:
Array ( [0] => even--heaped--heaped--feast [1] => even--trees--trees--feast [4] => heaped--feast--trees--feast )
which is not what i want. Any suggestions (sorry about the terrible variable names).
This might help you:
$in = array(
"even--heaped",
"even--trees",
"hardrocks--cocked",
"pebbles--temple",
"heaped--feast",
"trees--feast"
);
$clusters = array();
foreach( $in as $item ) {
$words = explode("--", $item);
// check if there exists a word in an existing cluster...
$check = false;
foreach($clusters as $k => $cluster) {
foreach($words as $word) {
if( in_array($word, $cluster) ) {
// add the words to this cluster
$clusters[$k] = array_unique( array_merge($cluster, $words) );
$check = true;
break;
}
}
}
if( !$check ) {
// create a new cluster
$clusters[] = $words;
}
}
// merge back
$out = array();
foreach( $clusters as $cluster ) {
$out[] = implode("--", $cluster);
}
pr($out);
Try this code:
<?php
$data = array ("1--2", "3--1", "4--5", "2--6");
$n = count($data);
$elements = array();
for ($i = 0; $i < $n; ++$i)
{
$split = explode("--", $data[$i]);
$word_num = NULL;
foreach($split as $word_key => $word)
{
foreach($elements as $key => $element)
{
if(isset($element[$word]))
{
$word_num = $key;
unset($split[$word_key]);
}
}
}
if(is_null($word_num))
{
$elements[] = array();
$word_num = count($elements) - 1;
}
foreach($split as $word_key => $word)
{
$elements[$word_num][$word] = 1;
}
}
//combine $elements into words
foreach($elements as $key => $value)
{
$words = array_keys($value);
$elements[$key] = implode("--", $words);
}
var_dump($elements);
It uses $elements as an array of hashes to store the individual unique words as keys. Then combines the keys to create appropriate words.
Prints this:
array(2) {
[0]=>
string(10) "1--2--3--6"
[1]=>
string(4) "4--5"
}
Here is a solution with a simple control flow.
<?php
$things = array('even--heaped', 'even--trees', 'hardrocks--cocked',
'pebble--temple', 'heaped--feast' ,'trees--feast');
foreach($things as $thing) {
$str = explode('--', $thing);
$first = $str[0];
$second = $str[1];
$i = '0';
while(true) {
if(!isset($a[$i])) {
$a[$i] = array();
array_push($a[$i], $first);
array_push($a[$i], $second);
break;
} else if(in_array($first, $a[$i]) && !in_array($second, $a[$i])) {
array_push($a[$i], $second);
break;
} else if(!in_array($first, $a[$i]) && in_array($second, $a[$i])) {
array_push($a[$i], $first);
break;
} else if(in_array($first, $a[$i]) && in_array($second, $a[$i])) {
break;
}
$i++;
}
}
print_r($a);
?>
It seems you have already selected user4035's answer as best.
But i feel this one is optimized(Please correct me if i am wrong): eval.in
Code:
$array = Array ( 'even--heaped' , 'even--trees' ,'hardrocks--cocked' , 'pebbles--temple' , 'heaped--feast' , 'trees--feast' );
print "Input: ";
print_r($array);
for($j=0;$j < count($array);$j++){
$len = count($array);
for($i=$j+1;$i < $len;$i++){
$tmp_array = explode("--", $array[$i]);
$pos1 = strpos($array[$j], $tmp_array[0]);
$pos2 = strpos($array[$j], $tmp_array[1]);
if (!($pos1 === false) && $pos2 === false){
$array[$j] = $array[$j] . '--'.$tmp_array[1];unset($array[$i]);
}elseif(!($pos2 === false) && $pos1 === false){
$array[$j] = $array[$j] . '--'.$tmp_array[0];unset($array[$i]);
}elseif(!($pos2 === false) && !($pos1 === false)){
unset($array[$i]);
}
}
$array = array_values($array);
}
print "\nOutput: ";
print_r($array);