Loop function until there is no specified needle in the haystack - php

I'm trying to build a function, that will check if the needle is in haystack, if it is then the function should loop until there is none.
So far I've built a function for random number generation. What that function does is it will create a random string then hash it with sha512. The function then extracts all the numbers from a string and multiplies it by 2.
It leaves me with a long line of numbers, then I'll use mt_rand to specify start and end point for strpos. After that I just return the number that was created randomly.
function randomNumber($suurus, $max){
mb_internal_encoding("UTF-8");
$possible="aábcdeéfghiíjklmnoóöópqrstuúüűvwxyzAÁBCDEÉFGHIÍJKLMNOÓÖŐPQRSTUÚVWXYZ";
$char = mb_substr($possible,rand(0, mb_strlen($possible) - 1),1);
$str = openssl_digest($char, 'sha512');
$str = preg_replace('/[^1-9.]+/', '', $str);
$str = $str*2;
$strLen = strlen($str)-5;
$strStart = mt_rand(1, $strLen);
$strEnd = mt_rand(1, $suurus);
$str = substr($str, $strStart, $strEnd);
while($str > $max){
$str = $str / 2;
}
return round($str);
The thing is that this number can't repeat, I need it to be unique at all times for my app.
I actually accomplished what I wanted with if else statements, but that means I have to write a long script of repeated if statements until I get the results I want. I really don't think this is the smartest way to do things.
if(!isset($voitjad)){
$voitjad[$vCounter][] = array(
'nimi' => $voitja,
'auhind' => $keyCode['v'.$vCount.''],
'rn' => $rN,
'siin' => 1,
'id' => $voitjaID
);
}else{
if(!exist($rN, $voitjad)){
$voitjad[$vCounter][] = array(
'nimi' => $voitja,
'auhind' => $keyCode['v'.$vCount.''],
'rn' => $rN,
'siin' => 1,
'id' => $voitjaID
);
}else{
$rN = randomNumber($atLength, $atCount);
$voitja = $attendcheckfb['attending'][$rN]['name'];
$voitjaID = $attendcheckfb['attending'][$rN]['id'];
if(!exist($rN, $voitjad)){
$voitjad[$vCounter][] = array(
'nimi' => $voitja,
'auhind' => $keyCode['v'.$vCount.''],
'rn' => $rN,
'siin' => 2,
'id' => $voitjaID
);
}else{ and so on....
I also tried with do-while loop, but I couldn't really get it working, I'm not sure what exactly I'm doing wrong here. If you can educate me, shoot me with information.
$nimed = array_values($nimed);
$voitja = $nimed[$rN]['name'];
$voitjaID = $nimed[$rN]['id'];
$voitjad[$vCounter][] = array(
'nimi' => $voitja,
'auhind' => $keyCode['v'.$vCount.''],
'rn' => $rN,
'siin' => 1,
'id' => $voitjaID
);
$oitjaCount++;
$rN = randomNumber($nimedLength, $nimedCount);
} while(!exist($rN, $voitjad));
If there's a way for me to get better randomly generated numbers, then please tell me, I'm open for suggestions. Meanwhile I need help with this needle, haystack thing.

You can either do it with a loop:
function get_unique_hashcode() {
global $hash_array;
do {
$hashcode = make_random_hashcode();
} while (in_array($hashcode, $hash_array));
$hash_array[] = $hashcode;
return $hashcode;
}
Or you can do it with recursion:
function get_unique_hashcode() {
global $hash_array;
$hashcode = make_random_hashcode();
if (in_array($hashcode, $hash_array)) {
return get_unique_hashcode();
} else {
$hash_array[] = $hashcode;
return $hashcode;
}
}
This is just a general structure, you may need to adjust it for your detailed needs.

Related

Search in Array and get specific string value

I have a Wordpress post meta that has multiple arrays like this.
$costdata = Array(
Array( 'cost_id' => 1, 'cost_category' => 'Travel', 'cost_amount' => '3540')
Array( 'cost_id' => 2, 'cost_category' => 'Materials', 'cost_amount' => '1644')
Array( 'cost_id' => 3, 'cost_category' => 'Travel', 'cost_amount' => '1800')
);
add_post_meta($project_id, 'costdata', $costdata);
What I want to do is to get all 'cost_amount' where 'cost_category' is "Travel"
This is what I've done so far. I get a blank value. No error.
$listtravelcost = get_post_meta($project_id, 'costdata');
/*Calculate Travel cost */
$found_Travel = array_search('Travel', array_column($listtravelcost, 'cost_category'));
$travelbudget = array_column($found_Travel, 'cost_amount');
$printtravelbudget = array_sum($travelbudget);
echo $printtravelbudget;
Instead of array_search, you should use array_filter. array_search will only return the first element it finds that is equal to your needle. array_filter will return all entries in an array, for which the function returns true.
$found_Travel = array_filter($listtravelcost, function($entry) {
return $entry['cost_category'] === 'Travel';
});
The rest of your code should work.
You can use loop:
$travelbudget = [];
foreach ($costdata as $arr) {
if ($arr['cost_category'] === "Travel") {
$travelbudget[] = $arr;
}
}

php build strings from array elements

I`ve got the following array:
$myarray = array(
2 => array(
'id' => '2',
'parent_id' => '1',
),
4 => array(
'id' => '4',
'parent_id' => '2',
),
3 => array(
'id' => '3',
'parent_id' => '1',
),
1 => array(
'id' => '1',
'parent_id' => '0',
)
);
and the goal is to have the following output:
1
1.2
1.2.4
1.3
The problem is that I need to do that without recursion. Here is some kind of an answer but the guys there are building tree while I need to have strings. I tried to use some kind of $basestring variable in order to know where am I, but still it did not work without recursion. Any ideas how to do that?
Thank you
UPD My first attempt was the following:
foreach($myarray as $k=>$value){
if($value['parent_id'] == 0){
$string = '1';
$id = $value['id'];
$newarr[0] = $string;
$basestring = $string.'.';
}elseif($value['parent_id'] == 1){
$string = $basestring.$value['id'];
$id = $value['id'];
$newarr[$id] = $string;
}elseif($value['one'] == 2){
$string = $basestring.$value['parent_id'].'.'.$value['id'];
$id = $value['id'];
$newarr[$id] = $string;
}elseif($value['parent_id'] == 3){
$string = $basestring.$value['parent_id'].'.'.$value['id'];
$id = $value['id'];
$newarr[$id] = $string;
}elseif($value['parent_id'] == 4){
$string = $basestring.$value['parent_id'].'.'.$value['id'];
$id = $value['id'];
$newarr[$id] = $string;
}//etc...
}
}
but obviously it failed due to non-scalability. I need to code somehow the iteration from child to parent here
An iterative solution could work something like this:
foreach ($myarray as $x) {
$temp = $x;
$string = [];
while (true) {
$string[] = $temp['id']; // add current level id
if (!isset($myarray[$temp['parent_id']])) break; // break if no more parents
$temp = $myarray[$temp['parent_id']]; // replace temp with parent
}
$strings[] = implode('.', array_reverse($string));
// array_reverse is needed because you've added the levels from bottom to top
}
Basically for each element of the array, create a temporary copy, then find its parents by key and set the temporary copy to the parent until no more parents are found. Add the ids into an array as you go and build the string from the array when you get to the end.
This assumes your array is valid, in that it does not contain circular references (e.g. one level being its own ancestor). To prevent an infinite loop if this did happen, you could increment a variable within the while loop and break if it reached some reasonable limit.

Localize markers in PHP Array

This is quite basic, but I am missing a puzzle piece.
I have a multidimensional PHP array that - among other things - contains some strings. I would like to translate special strings in this array based on a translation table or array in PHP.
$r = array(
0 => 'something',
1 => array(
'othertext' => '1000 {{animals}} and {{cars}}',
'anytext' => '400 {{cars}}',
)
);
In $r, now I would like to replace {{animals}} with another string that is stored in a separate array.
Here it is:
$translations = array(
'animals' => array('Tiere','animaux','bestie'),
'cars' => array('Autos','voitures','macchine'),
);
Now let's set the language / column we want to look up
$langId = 0;
And now, take $r, look for all key that are wrapped in {{}}, look them up in $translations and replace them with key[$langId], so in return we get:
$r = array(
0 => 'something',
1 => array(
'othertext' => '1000 Tiere',
'anytext' => '400 Autos',
)
);
ehm... how's that done?
PS: the marker {{}} is random, could be anything robust
I was able to get the output you expected using the following code. Try it and tell me if it worked for you or not:
<?php
$r = array(
0 => 'something',
1 => array(
'othertext' => '1000 {{animals}} and {{cars}}',
'anytext' => '400 {{cars}}',
)
);
$translations = array(
'animals' => array('Tiere','animaux','bestie'),
'cars' => array('Autos','voitures','macchine'),
);
$langId = 0;
$pattern = "/\{\{[a-zA-Z]+\}\}/";
for($t=0; $t<count($r); $t++) {
$row = $r[$t];
if(!is_array($row))
continue;
foreach($row as $key=>$value) {
if(preg_match_all($pattern, $value, $match, PREG_SET_ORDER)) {
for($i = 0; $i < count($match); $i++) {
//remove {{ & }} to get key
$k = substr($match[$i][0], 2, strlen($match[$i][0])-4);
$replacer = $translations[$k][$langId];
$value = str_replace($match[$i][0], $replacer, $value);
$r[$t][$key] = $value;
}
}
}
}
?>

Parse data into array

I'm creating a "quote database" for a TV show I'm a fan of, and I'm rewriting parts of it I don't particularly like. I came across my function to parse the data holding the quote and characters into an array that I can easily loop through and display. One of the features of the site is that you can have a single quote (one-liner) or a conversation between several characters. Right now I'm storing single quotes like this:
[charactername]This is my witty one-liner.
And conversations follow the same pattern:
[characternameone]How's the weather?
[characternametwo]Pretty good, actually.
And so on. Here's the aforementioned parsing function:
function parse_quote($text)
{
// Determine if it's a single or convo
if ( strpos($text, "\n") != false )
{
// Convo
// Let's explode into the separate characters/lines
$text = explode("\n", $text);
$convo = array();
// Parse each line into character and line
foreach ( $text as $part )
{
$character = substr($part, 1, strpos($part, ']') - 1);
$line = substr($part, strlen($character) + 2);
$convo[] = array(
'character' => $character,
'line' => $line
);
}
return array(
'type' => 'convo',
'quote' => $convo
);
}
else
{
// Single
// Parse line into character and line
return array(
'type' => 'single',
'quote' => array(
'character' => substr($text, 1, strpos($text, ']') - 1),
'line' => substr($text, strlen(substr($text, 1, strpos($text, ']') - 1)) + 2)
)
);
}
}
It works as expected, but I can't help but think there's a better way to do this. I'm horrible with regular expressions, which I assume would come in at least somewhat handy in this situation. Any advice, or improvements?
Personally, I would change your data storage method. It would be much easier to deal with a serialized or JSON encoded string.
Instead of
[characternameone]How's the weather?
[characternametwo]Pretty good, actually.
you would have
array(
[0] => {
'name' => "characternameone",
'quote' => "How's the weather?"
},
[1] => {
'name' => "characternametwo",
'quote' => "Pretty good, actually"
}
)
Then when you read it out, there isn't any parsing.
function display_quote($input)
{
for ($i=0, $n=count($input); $i<$n; $i++) {
$quote = $input[$i];
if ( $i > 0 ) echo "\n";
echo $quote['name'] . ': ' . $quote['quote'];
}
}
Instead of
$character = substr($part, 1, strpos($part, ']') - 1);
$line = substr($part, strlen($character) + 2);
$convo[] = array(
'character' => $character,
'line' => $line
);
you could try
preg_match('#\[([^\]]+)\](.*)#ism', $part, $match);
$convo[] = array(
'character' => $match[1],
'line' => $match[2]
);
HTH

Array as folders

I did this code:
index.php:
$series = array(
"a" => array(
"b" => array(
"FOLD", "more_arrays.php"
),
"b2" => array(
)
)
);
function pre($a) { print "<pre>"; print_r($a); print "</pre>"; }
$string = "a,,,b";
$all_directions = explode(",,,", $string);
$all_directions = array_map("trim", $all_directions);
$b = ""; $g = 0;
foreach($all_directions as $v)
{
$b .= "['".str_replace(array("[", "]", "'", "\""), null, $v)."']";
$g++;
}
#eval('$where = $series'.$b.';');
if(isset($where[0]) && $where[0] == "FOLD")
{
// a[series], b[series], c[new_array]
require_once("./more_folders/".$where[1]);
print $g;
}
for($i = 0; $i <= sizeof($where); $i++)
{
}
pre($where);
more_array.php:
$series_in = array(
"c" => array(
"d" => array(
"bla" => array(),
"hey" => array(),
"ha" => array()
),
"d2" => array(
)
),
"c2" => array(
)
)
At $string I define which "folder" I want to see, for example if I write $string = "a"; it will show all the arrays inside "a".
key = the name of the folder, value = the subfolders inside the folder and those array.
Now: Because it's going to be a huge array, I want to separate it to many arrays.
If you see at the code, $series[a][b] direct lead to another array.
Now if I do $string = "a,,,b"; I want to see: "c" and "c2"
and if I do $string = "a,,,b,,,c"; I want to see: "d", "d2"
and if I do $string = "a,,,b,,,c,,,d"; I want to see all inside d ( "bla", "hey", "ha" ..)
How can I do this?
I'll bite...
You seem to have most of the parts. Basically you need to put them together in a loop.
You've $string and $series. Then you split $string into your $all_directions. Loop thru $all_directions, each time diving down into the array $series = $series[$all_directions[$i]]; When you've done the last $all_directions return $series (but watch for running out of $series, return null, or false if you're sure that would be an error).
The only other thing is any time $series[$all_directions[$i]] is the special "FOLD" entry then first load the file and assign it on-the-fly something like
include ...;
$series[$all_directions[$i]] = $series_in;
You don't want and don't need eval() and the loop is better using for because you need to check "FOLD" in the key (I'd also say use a recursive function but you said the array can be very big so it might hurt performance).

Categories