Read consecutive lines from file into key => value array - php

I am trying to convert a user/pass txt file to an array, I tried to do this with a foreach, explode, reg_split, but didn't get anything working in the right way.
Also a blank line should be skipped...
Example text file:
username1
password1
username2
password2
username3
password4
Example array:
array(
$username1 => $password1,
$username2 => $password2
)

Create an array of pairs from the consecutive lines, then combine the column of keys with the column of values:
$chunks = array_chunk(
file('userpass.txt', FILE_SKIP_EMPTY_LINES|FILE_IGNORE_NEW_LINES),
2
);
$users = array_combine(
array_column($chunks, 0),
array_column($chunks, 1)
);
Explanation
$chunks is an array of arrays: each inner array has two elements: #0 is the username (first line) and #1 is the password (second line). Using file to skip blank lines and remove trailing new-lines keeps this code simple, but not bullet-proof.
$users then is made by taking all the usernames (index 0 from all the inner arrays) and pointing them to all the passwords (index 1).
You can accomplish the same with a loop over $chunks. However, I prefer this approach because all looping is handled inside the engine, where it is marginally more performant.

Split the file into one array and then combine them into a new array with key-value pairs
$file = file("usernames.txt", FILE_SKIP_EMPTY_LINES|FILE_IGNORE_NEW_LINES);
$array = [];
for($i = 0; $i < count($file) - 1; $i++){
$array[$file[$i]] = $file[$i + 1];
}

I have to think on it, but I know you can read the file into an array using php's file() method.
$var = file("myFile.txt", FILE_SKIP_EMPTY_LINES);

Related

Selecting multiple substrings from a string

I am a newbie here and I have a php array of some strings, such as {"VAL1","VAL2", "VAL3", "VAL4"} and I have a larger string (normally a text file). The text file contains the elements of the arrays at different positions and some or all may be repeating more than one. Each of of the elements of the array that are contained in the text file are immediately followed by a time of occurence, for example, "VAL1 0900UTC and other text information".The problem now is that I want to find the occurrence(s) of all of the elements of the array in the text file and the time value following the element.
Please note that some of the elements may occur more than once at different positions with different time value in the textfile.
Already, I can load the textfile and get all of the elements.:
$mytextfile = preg_replace('/\s+/', ' ', strtoupper(file_get_contents($textpath."/". $textfile)));
$substr = array("REALTK","BGPTK", "SUDTK", "BECTK");
$bigstring = "REALTK 1000UTC 16/14 1011 BGPTK 1030UTC 10/12 992 REALTK 1145UTC 00/14 2222 SUDTK 1412UTC 11/06 1011 REALTK 1600UTC 16/14 1015 ...";
//I created variables to hold all element occuring to false
$is_val1 = false; $is_val2 = false;$is_val3 = false; $is_val4 = false;
//I created variables to count how many of each substring exist in the string
$numofval1=$numofval2=$numofval3=$numofval4=0;
if(strpos($bigstring, $substr[0]) !== false) {
$is_val1 = true;
//if exist, count how many times
$numofval1 = substr_count(strtoupper($bigstring),$substr[0]);
} e.t.c
I have been able to get the occurrence of each of the array elements in the big string
I have been able to detect if any of the array elements occur more than once in big string and number of times it does.
But I have not being able to get them in the sequence they occur with their position in the textfile string and the time value after each element.
$mytextfile = preg_replace('/\s+/', ' ', strtoupper(file_get_contents($textpath."/". $textfile)));
$substr = array("REALTK","BGPTK", "SUDTK", "BECTK");
//this is a sample content of the textfile
$bigstring = "REALTK 1000UTC 16/14 1011 BGPTK 1030UTC 10/12 992 REALTK 1145UTC 00/14 2222 SUDTK 1412UTC 11/06 1011 REALTK 1600UTC 16/14 1015 ...";
//I created variables to hold all element occuring to false
$is_realtk = false; $is_bgptk = false;$is_sudtk = false; $is_bectk = false;
//I created variables to count how many of each of the element exist in the text file string
$numofrealtk=$numofbgptk=$numofsudtk=$numofbectk=0;
if(strpos($bigstring, $substr[0]) !== false) {
$is_realtk = true;
//if exist, count how many times
$numofrealtk = substr_count(strtoupper($bigstring),$substr[0]);
} e.t.c
What I need is to get the Elements of the array in the order in which they occur in the text file with their position and time value
REALTK POSITION1 1000UTC
BGPTK POSITION5 1030UTC
REALTK POSITION8 1145UTC
SUDTK POSITION13 1412UTC
REALTK POSITION17 1600UTC
I also want to store the element => timevalue as associative array.
Thanks in anticipation.
Here is the snippet for you, please see inline doc for explanation
$substr = array("VAL1","VAL2", "VAL3", "VAL4");
$bigstring = "OTHERS VAL1 VAL4 VAL1 OTHERS OTHERS VAL2 OTHERS";
// considering space to explode words and having numbers in it
$temp = array_unique(str_word_count($bigstring, 1,"0..9"));
// sorting generated array and keeping index of value
asort($temp);
// matching records from array
$temp = array_intersect($temp,$substr);
// showing all the data you want
array_walk($temp,function($item,$k){
echo $item.' POSITION '.$k."\n"; // replace \n with <br/> if web
});
Working demo.
If the elements in your $bigstring are always divided by a whitespace, you can explode:
$val_arr = array( "REALTK" => array(), "BGPTK" => array(), "SUDTK" => array(), "BECTK" => array();
$bigstring_arr = explode( " ", $bigstring);
foreach( $bigstring_arr as $key => $part ){
if( in_array( $part, $substr ) ){
$val_arr[$part][] = array( "position" => $key+1, "time" => $bigstring_arr[$key+1] );
}
}
If it's not you can also explode directly on each element of Val1, Val2... . The code gets a bit more complicated then. But it would work as well if you created a new array in the form of "CountOfAllCharsInBigstringBeforeOccurence" => "KeyOfValInSubstr". From that you can derive your ordering with the vals.
Edit:
I edited the code based on your comment. Please note that it is not possible to have an array that has the same key multiple times which is why the solution here will have multiple dimensions.

PHP / json encode wrongly interprets as associative array

Edit1: The problem: I want to convert in php a associative array to a indexed one. So I can return it via json_encode as an array and not as an object. For this I try to fill the missing keys. Here the description:
Got a small problem, I need to transfer a json_encoded array as an array to js. At the moment it returns an Object. I´m working with Angular so I really need an Array. I try to explain it as much as possible.
$arrNew[0][5][0][0][1]["id"] = 1;
//$arrNew[0][0][0][0][1] = "";
//$arrNew[0][1][0][0][1] = "";
//$arrNew[0][2][0][0][1] = "";
//$arrNew[0][3][0][0][1] = "";
//$arrNew[0][4][0][0][1] = "";
$arrNew[0][5][0][0][1]["name"] = 'Test';
var_dump($arrNew);
So if I return it now It returns the second element as object cause of the missing index 0-4 and the 4th element cause of the missing index 0 (associative array -> object)
So if I uncomment the block it works like a charm. Now I have the problem its not every time the element 5 sometime 3, 4 or something else so I build a function which adds them automaticly:
$objSorted = cleanArray($arrNew);
function cleanArray($array){
end($array);
$max = key($array) + 1; //Get the final key as max!
for($i = 0; $i < $max; $i++) {
if(!isset($array[$i])) {
$array[$i] = '';
} else {
end($array[$i]);
$max2 = key($array[$i]) + 1;
for($i2 = 0; $i2 < $max2; $i2++) {
.... same code repeats here for every index
So if I vardump it it returns:
The problem:
On js side its still an object, what I also see is that the elements are not sorted. So I think somehow PHP sees it still as an associative array. Any clue why this happens ? The key is set with the index of the loop and has to be a integer value.
PS: I know reworking it in JS is possible but would have be done nearly on every request with a huge load of loops
If I understand your problem, you create a sparse multidimensional array of objects. Because the arrays have gaps in the keys, json_encode() produces objects on some levels but you need it to produce arrays for all but the most inner level.
The following function fills the missing keys (starting from 0 until the maximum value used as numeric key in an array) on all array levels. It then sorts each array by their keys to make sure json_encode() encodes it as array and not object.
The sorting is needed, otherwise json_encode() generates an object; this behaviour is explained in a note on the json_encode() documentation page:
When encoding an array, if the keys are not a continuous numeric sequence starting from 0, all keys are encoded as strings, and specified explicitly for each key-value pair.
// If $arr has numeric keys (not all keys are tested!) then returns
// an array whose keys are a continuous numeric sequence starting from 0.
// Operate recursively for array values of $arr
function fillKeys(array $arr)
{
// Fill the numeric keys of all values that are arrays
foreach ($arr as $key => $value) {
if (is_array($value)) {
$arr[$key] = fillKeys($value);
}
}
$max = max(array_keys($arr));
// Sloppy detection of numeric keys; it may fail you for mixed type keys!
if (is_int($max)) {
// Fill the missing keys; use NULL as value
$arr = $arr + array_fill(0, $max, NULL);
// Sort by keys to have a continuous sequence
ksort($arr);
}
return $arr;
}
// Some array to test
$arrNew[0][5][0][0][1]["id"] = 1;
$arrNew[0][3][0][2][1]["id"] = 2;
$arrNew[0][5][0][0][1]["name"] = 'Test';
echo("============= Before ==============\n");
echo(json_encode($arrNew)."\n");
$normal = fillKeys($arrNew);
echo("============= After ==============\n");
echo(json_encode($normal)."\n");
The output:
============= Before ==============
[{"5":[[{"1":{"id":1,"name":"Test"}}]],"3":[{"2":{"1":{"id":2}}}]}]
============= After ==============
[[null,null,null,[[null,null,[null,{"id":2}]]],null,[[[null,{"id":1,"name":"Test"}]]]]]
The line $arr = $arr + array_fill(0, $max, NULL); uses NULL as values for the missing keys. This is, I think, the best for the Javascript code that parses the array (you can use if (! arr[0]) to detect the dummy values).
You can use the empty string ('') instead of NULL to get a shorter JSON:
[["","","",[["","",["",{"id":2}]]],"",[[["",{"id":1,"name":"Test"}]]]]]
but it requires slightly longer code on the JS side to detect the dummy values (if (arr[0] != '')).

Php generate multiple array() without duplicate value and match with other array?

I have 2 data.
$dataA = 01,05,07;
$dataB = 01,07;
Now, I would like to explode the $dataA and combine back with only 2 string. like below:
$explode = explode(',',$dataA);
/*combine back get the max combination without duplicate string, example for the $dataA.
My suspect is: first array (01,05), second array(05,07), third array(07,01), I don't need (05,01) since first array have both value.
*/
After that, if the combination array value match with the $dataB (no matter which the value position is), then do something like:
$array[0] = '01,05';
$array[1] = '05,07';
$array[2] = '07,01';
//since $array[2] value = $dataB (no need to check specific position); so I would like to do as below
if(in_array(third array,$dataB)){ //use in_array or?
//do something
}
Is it any array function can done this?

PHP make N copies of array with functions

In my code I need to make a number of copies of a dummy array. The array is simple, for example $dummy = array('val'=> 0). I would like make N copies of this array and tack them on to the end of an existing array that has a similar structure. Obviously this could be done with a for loop but for readability, I'm wondering if there are any built in functions that would make this more verbose.
Here's the code I came up with using a for loop:
//example data, not real code
$existingArray = array([0] => array('val'=>2),[1] => array('val'=>3) );
$n = 2;
for($i=0;$i<$n;$i++) {
$dummy = array('val'=>0); //make a new array
$existingArray[] = $dummy; //add it to the end of $existingArray
}
To reiterate, I'd like to rewrite this with functions if such functions exist. Something along the lines of this (obviously these are not real functions):
//make $n copies of the array
$newvals = clone(array('val'=>0), $n);
//tack the new arrays on the end of the existing array
append($newvals, $existingArray)
I think you're looking for array_fill:
array array_fill ( int $start_index , int $num , mixed $value )
Fills an array with num entries of the value of the value parameter, keys starting at the start_index parameter.
So:
$newElements = array_fill(0, $n, Array('val' => 0));
You do still have to handle the appending of $newElements to $existingArray yourself, probably with array_merge:
array array_merge ( array $array1 [, array $... ] )
Merges the elements of one or more arrays together so that the values of one are appended to the end of the previous one. It returns the resulting array.
If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, but will be appended.
Values in the input array with numeric keys will be renumbered with incrementing keys starting from zero in the result array.
So:
$existingArray = array_merge($existingArray, $newElements);
This all works because your top-level arrays are numerically-indexed.

explode string and set key for array with text that is in front of the delimiter?

Is there a way to take an input like this:
|
testing==one two three
|
setting==more testing
|
and get something like this
array['testing'] = "one two three";
array['setting'] = "more testing"
Right now I'm just exploding the string and setting the array with numbered index, but I'd like the user to be able to enter the items in any order and be able to use the array with keys from the first value.
function get_desc_second_part(&$value) {
list(,$val_b) = explode('==',$value);
$value = trim($val_b);
}
Thanks!
Something like this? The pipes adds some maybe needless complexity (separator could be new lines):
$arr = array();
foreach (explode('|', $str_input) as $line) {
$l = explode('==', trim($line));
if (isset($l[1]))
$arr[$l[0]] = $l[1];
}
print_r($arr);
/*
Array
(
[testing] => one two three
[setting] => more testing
)
*/
If you can change the format of the input to the standard ini format then you could simply call parse_ini_file/parse_ini_string. Your input would need to look like:
testing = one two three
setting = more testing
This would also give you comments (start lines with ;) and sections for free. See http://www.php.net/parse_ini_file
You already do most of the work when you explode on ==, an array index can be manually set to a string and you already separate out the string. Just set your array entries manually,
$myarray = new array();
$myarray[$your_exploded_1st_part_string_here] = exploded_second_part

Categories