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.
Related
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've been struggling with this for a few days and wanted to throw it out there and see if someone has any ideas.
Basically I have a string e.g
1) "/0/bar"
2) "/build/0/foo/1"
and need to convert this into a multidimensional array
1) $result[0][bar]
2) $result[build][0][foo][1]
So far I've tried:
$query = "/build/0/foo/1";
$queryAr = [];
$current = &$queryAr;
$keys = explode("/", $query);
foreach($keys as $key) {
#$current = &$current[$key];
}
$current = $value;
quieting the output is a pretty hacky way to achive this...
You need to trim the first / of the string. live demo.
<?php
$query = "/build/0/foo/1";
$queryAr = [];
$current = &$queryAr;
$keys = explode("/", trim($query, '/'));
foreach($keys as $key) {
#$current = &$current[$key];
}
$current = $value;
print_r($queryAr);
I tried a recursive function version:
$query = "/build/0/foo/1";
print_r($result = buildNestedArray(explode('/', trim($query, '/'))));
function buildNestedArray($keys)
{
$k = current($keys);
$result = [$k => 'DONE'];
array_shift($keys);
if (sizeof($keys) > 0) { $result[$k] = buildNestedArray($keys); }
return $result;
}
output: Array ( [build] => Array ( [0] => Array ( [foo] => Array ( [1] => DONE ) ) ) )
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);
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);
Can someone please give me a hand making this explode function recursive? My head is not working today.
function expl($str,$charlist='|'){
$charlist = str_split($charlist);
foreach($charlist as $char){
if(is_array($str)){
for($i=0; $i<sizeof($str); $i++){
$str[$i] = expl($str[$i],$char);
}
}else{
return (explode($char,trim($str,$char)));
}
}
return($str);
}
echo "<pre>";
print_r(expl("A~a1~a2|B~b1~b2",'|~'));
echo "</pre>";
Should output:
Array
(
[0] => Array
(
[0] => A
[1] => a1
[2] => a2
)
[0] => Array
(
[0] => B
[1] => b1
[2] => b2
)
)
<?php
function expl($str, $charlist = '|')
{
if (!$charlist) {
return $str;
}
$char = $charlist[0];
$matrix = explode($char, $str);
for ($i = 0; $i < sizeof($matrix); $i++) {
$matrix[$i] = expl($matrix[$i], substr($charlist, 1));
}
return $matrix;
}
echo "<pre>";
print_r(expl("A~a1~a2|B~b1~b2", '|~'));
echo "</pre>";
that would be something like this...
use recursion!
the first level will get the first matrix, doing something like this
$matrix[0] = "A~a1~a2";
$matrix[1] = "B~b1~b2";
and then, the recursion will do the second part, which will make each string become the array of strings, that will become the array of strings until there's no more separators.
The below is a working example, and I've provided a link to show you the output when the function is run:
Example return:
http://phpfiddle.org/api/run/4iz-i2x
Usage:
echo '<pre>';
print_r( expl("A~a1~a2|B~b1~b2",'|~'));
echo '</pre>';
Function:
<?php
function expl($str,$charlist='|', $currentChar = 0, $continue = true){
if(!$continue)
{
return $str;
}
$endArray = array();
if($currentChar == 0){
$charlist = str_split($charlist);
}
else
{
if($currentChar > count($charlist))
{
return expl($str, $charlist, $currentChar, false);
}
}
if(!is_array($str))
{
$pieces = explode($charlist[$currentChar], $str);
$currentChar++;
return expl($pieces, $charlist, $currentChar);
}
else{
foreach($str as $arrayItem){
if(is_array($arrayItem))
{
return expl($str, $charlist, $currentChar, false);
}
$endArray[] = explode($charlist[$currentChar], $arrayItem);
}
$currentChar++;
return expl($endArray, $charlist, $currentChar);
}
}
?>
Simply do like this.First explode by '|' then by '~'. it should be something like this:
$str="A~a1~a2|B~b1~b2";
$arr=explode("|",$str);
$result=array();
foreach($arr as $k=>$v)
{
$arr1=explode("~",$v);
$result[]=$arr1;
}