Assign key number to php array objects - php

My code
$str = array(fgets($da, 1024));
print_r($str);
I'm trying to create an array in php from a dynamic output , but i noticed the keys in all object are [0], i need to assign a diferent key number to each object, how can i do that ?
Looks weird to me that all keys are 0, im trying to figure but nothing helps me.
Result :
Array
(
[0] =>
)
Array
(
[0] => 200
)
Array
(
[0] => 819105 rs fs
)
Array
(
[0] => 300 tert
)
Array
(
[0] => THO
)
Array
(
[0] => 91362
)
Array
(
[0] =>
)
Array
(
[0] => 06-20-21 6:56 PM
)
Array
(
[0] =>
)
Array
(
[0] =>
Array
(
[0] => 3 Cat 20 4.82 0.0 7.4 30
)
Array
(
[0] => 4 Dogs 19 26.2 0.8 7.1 62
)
Array
(
[0] =>
)
Thanks

If the input is reliable, you can split on whitespace for example:
$str = fgets($da, 1024);
$a = explode(" ", $str);
print_r($a);

array_merge with the spread (...) operator would work.
$str = array(fgets($da, 1024));
$str = array_merge(...$str);

All of the keys appear to be zero because you are wrapping each line from the file in its own array, so each array has one element at index zero.
If you define a buffer outside of your read loop, and add each line to it, each line will have its own index.
$da = fopen('test.txt', 'r');
// Define a buffer for the output
$data = [];
while (($str = fgets($da)) !== false)
{
// Add our line to the buffer
$data[] = $str;
}
fclose($da);
print_r($data);
output:
Array
(
[0] => 200
[1] => 819105 rs fs
[2] => 300 tert
[3] => THO
[4] => 91362
[5] => 06-20-21 6:56 PM
[6] => 3 Cat 20 4.82 0.0 7.4 30
[7] => 4 Dogs 19 26.2 0.8 7.1 62
)
But it looks like you may have some sort of header information in the first 6 lines of the file, maybe info from an HTTP request? Then lines that are somehow delimited, maybe by tab, but then the text got munged somewhere on the way into the SO post?
You can use a combination of fgets and fgetcsv to pull the data from the file and organize it into associative arrays.
Input:
200
819105 rs fs
300 tert
THO
91362
06-20-21 6:56 PM
3 Cat 20 4.82 0.0 7.4 30
4 Dogs 19 26.2 0.8 7.1 62
5 Wombat 20 4.20 0.0 6.9 30
6 Hedgehogs 19 26.2 0.8 7.1 62
$da = fopen('test.txt', 'r');
// Define a buffer for the output
$data = [];
// Define the fields in the header, each header line needs an entry
$headerDef = [
'status',
'transfer_stats',
'what_is_this',
'something_else',
'content_length',
'timestamp'
];
// Define the columns in the data rows, each column needs an entry
$columnDef = [
'id',
'type',
'count',
'average_weight',
'tax',
'food_weight_percent_per_day',
'fluffiness'
];
// Define an array to hold the header contents
$headerData = [];
// For each line in the header definition, extract a line from the file
while (!empty($headerDef) && $str = fgets($da, 1024))
{
$currValue = trim($str);
// Pull the next field from the front of the array
$currHeaderField = array_shift($headerDef);
// Set the entry in the header data array
$headerData[$currHeaderField] = $currValue;
}
while ($row = fgetcsv($da, 1024, "\t"))
{
// Create a new associative array by combining the column names and the row data
$data[] = array_combine($columnDef, $row);
}
fclose($da);
print_r($headerData);
print_r($data);
output:
Array
(
[status] => 200
[transfer_stats] => 819105 rs fs
[what_is_this] => 300 tert
[something_else] => THO
[content_length] => 91362
[timestamp] => 06-20-21 6:56 PM
)
Array
(
[0] => Array
(
[id] => 3
[type] => Cat
[count] => 20
[average_weight] => 4.82
[tax] => 0.0
[food_weight_percent_per_day] => 7.4
[fluffiness] => 30
)
[1] => Array
(
[id] => 4
[type] => Dogs
[count] => 19
[average_weight] => 26.2
[tax] => 0.8
[food_weight_percent_per_day] => 7.1
[fluffiness] => 62
)
[2] => Array
(
[id] => 5
[type] => Wombat
[count] => 20
[average_weight] => 4.20
[tax] => 0.0
[food_weight_percent_per_day] => 6.9
[fluffiness] => 30
)
[3] => Array
(
[id] => 6
[type] => Hedgehogs
[count] => 19
[average_weight] => 26.2
[tax] => 0.8
[food_weight_percent_per_day] => 7.1
[fluffiness] => 62
)
)
Of course the field names are just made up, I have no idea what your actual data is. And I'm assuming that the data rows are delimited with tabs, that may not be the case. But you should be able to use this as a starting point.
PS. It could be that the HTTP data at the top of the file is included by mistake, perhaps from a curl request? You could change that with the CURLOPT_HEADER option and curl_setopt

Related

Preserve keys array_splice from another array

I am trying to keep keys from an array that i am counting and splicing trough array_splice function. There looks like that i am using wrong method to achieve my goal but i wanted to see if it's possible iwth array_splice
I have 2 arrays:
Task
Employees
Task and Employee (absent) array:
$task_id = ['998', '997', '996', '995', '995', '995', '995', '995', '995', '995', '995', '995'];
$absent = array(
[
'employee' => 'POL',
'absent_from' => '',
'absent_to' => ''
],
[
'employee' => 'FAR',
'absent_from' => '2021-07-12',
'absent_to' => '2021-07-16'
],
[
'employee' => 'FARs',
'absent_from' => '2021-07-12',
'absent_to' => '2021-07-16'
],
[
'employee' => 'FARss',
'absent_from' => '2021-07-12',
'absent_to' => '2021-07-16'
],
[
'employee' => 'FARsss',
'absent_from' => '2021-07-12',
'absent_to' => '2021-07-16'
],
);
What i am trying to achieve:
I want to delegate task_id equal to all employees. So for example i have 10 task and 10 employees i want to divide the tasks to 10 and delegate them to employees. If i have 9 task and 10 employees then everyone will get 2 task but one of them will only get 1 task.
First i add the names in another array from $absent array:
$absent_name = array();
foreach($absent as $key => $name) {
$absent_name[$key] = $name['employee'];
}
Then i try to splice the task_id among the employees (with counting the employees):
$output = array(); // Output / Result (Array)
$input = $task_id; // Tasks (ids)
$num_employees = count($absent_name); // number of employees
for (;$num_employees > 0; $num_employees -= 1) {
$output[] = array_splice($input, 0, ceil(count($input) / $num_employees));
}
print_r($output);
The result is this: (i have tested with more/less employees and task_id and looks like the result array is dividing just like i want it to but i want to keep the names not keys):
Array
(
[0] => Array
(
[0] => 998
[1] => 997
[2] => 996
)
[1] => Array
(
[0] => 995
[1] => 995
[2] => 995
)
[2] => Array
(
[0] => 995
[1] => 995
)
[3] => Array
(
[0] => 995
[1] => 995
)
[4] => Array
(
[0] => 995
[1] => 995
)
)
What i need:
Array
(
[POL] => Array
(
[0] => 998
[1] => 997
[2] => 996
)
[FAR] => Array
(
[0] => 995
[1] => 995
[2] => 995
)
[FARs] => Array
(
[0] => 995
[1] => 995
)
[FARss] => Array
(
[0] => 995
[1] => 995
)
[FARsss] => Array
(
[0] => 995
[1] => 995
)
)
or something simple just so i can add it easly in a DB:
Array
(
[POL] => [998,997,996]
)
[FAR] => [995,995,995]
)
etc......
)
Any idea if i need to change method or can i use array_splice?
I don't think array_splice is going to do any favors for you here, IMO you are working to hard, and should let PHP's array functions do most of the work for you. You can then concentrate on your business logic, which is pretty simple.
Use array_column to easily extract the emplyee IDs from the $absent array.
Use array_map to create and initialize an associative array of arrays, keyed by employee ID.
Loop through the task IDs and use the key, next, and reset functions to advance through the assignment map and wrap around as needed.
// Create an associative array keyed by the employee IDs
$employeeTaskMap = array_flip(array_column($absent, 'employee'));
// Initialize the values to empty arrays
$employeeTaskMap = array_map(fn() => [], $employeeTaskMap);
// Loop through the task IDs
foreach ($task_id as $currTaskId)
{
// Add the task ID to the array at the current pointer in the $employeeTaskMap
$employeeTaskMap[key($employeeTaskMap)][] = $currTaskId;
// Advance the array pointer, reset when we reach the end so we can wrap around
if (next($employeeTaskMap) === false)
{
reset($employeeTaskMap);
}
}
print_r($employeeTaskMap);
Output:
Array
(
[POL] => Array
(
[0] => 998
[1] => 995
[2] => 995
)
[FAR] => Array
(
[0] => 997
[1] => 995
[2] => 995
)
[FARs] => Array
(
[0] => 996
[1] => 995
)
[FARss] => Array
(
[0] => 995
[1] => 995
)
[FARsss] => Array
(
[0] => 995
[1] => 995
)
)
If you really want to use array_splice here for some reason and get your existing code working, use array_combine at the end to use the values of your employee names array as the keys for the output:
$taskBuffer = array(); // Output / Result (Array)
$input = $task_id; // Tasks (ids)
$num_employees = count($absent_name); // number of employees
for (; $num_employees > 0; $num_employees -= 1)
{
$taskBuffer[] = array_splice($input, 0, ceil(count($input) / $num_employees));
}
$output = array_combine($absent_name, $taskBuffer);
This works, but you are having to implement a lot of lower level logic that is unnecessary if you use a simpler, more declarative approach. That introduces more possibility for errors in your code, and makes it difficult for developers who may work with your code (including you six month from now) to understand what you are doing at a glance.

How to make array intersect in php? [duplicate]

This question already has answers here:
How to remove duplicate values from an array in PHP
(27 answers)
Closed last year.
This is my two arrays:
$head_office = array(600,400,534,678,601,90);
$Sb_office = array(600,400,530,678,600,90,84);
My desire output:
array(600,400,678,90);
I am trying:
print_r(array_intersect($Sb_office,$head_office));
Output:
Array ( [0] => 600 [1] => 400 [3] => 678 [4] => 600 [5] => 90 )
How can I avoid the value 600 ?
NB: I am not removing duplicate values. I want to get matched values between 2 arrays.
Use array_unique().
$head_office = array(600,400,534,678,601,90);
$Sb_office = array(600,400,530,678,600,90,84);
print_r(array_unique(array_intersect($Sb_office,$head_office)));
Output
Array ( [0] => 600 [1] => 400 [3] => 678 [5] => 90 )
It seams that you want to avoid duplicate value 600. you can do it using array_unique() like below
print_r(arry_unique(array_intersect($Sb_office,$head_office)));
Use array_unique
Additionally you can use array_values to alter the keys of new array.
$head_office = array(600,400,534,678,601,90);
$Sb_office = array(600,400,530,678,600,90,84);
print_r(array_values(array_unique(array_intersect($Sb_office,$head_office))));
OUTPUT
Array ( [0] => 600 [1] => 400 [2] => 678 [3] => 90 )
Swap $head_office and $Sb_office
<?php
$head_office = array(600,400,534,678,601,90);
$Sb_office = array(600,400,530,678,600,90,84);
print_r( array_intersect($head_office, $Sb_office) );
Output:
Array
(
[0] => 600
[1] => 400
[3] => 678
[5] => 90
)
I have gotten a partial answer:
print_r( array_intersect_assoc($head_office, $Sb_office) );

PHP array in array - DXF script

I found a php script to write DXF file based on coordinates of polygon. IT works on the test file with this code (for polygon):
$d->append(new DxfPolyLine(array('points'=>array(array(1, 1),
array(20, 10),
array(20, 20),
array(1, 15)),
'lineType'=>'DASHED',
// 'layer' => 'DXFWRITER',
'flag' => 0
//'width' => 1,
//'color'=>1
)
));
The DXF file result is like this:
VERTEX
8
0
6
DASHED
10
20.000
20
20.000
0
VERTEX
8
0
6
DASHED
10
1.000
20
15.000
0
A lot of vertex's inside a polyline.
Now I am trying to insert my own coordinates. I have the coordinates but how can I write an array in that array?
I have this: $g=array_merge($g,array(array($coord[$z]*3.527785, $coord[$z+1]*3.527785)));
With this code the result is:
Array ( [0] => Array ( [0] => -133.92170714209 [1] => -41.834100838885 ) [1] => Array ( [0] => -135.19600658422 [1] => -44.558002415365 ) [2] => Array ( [0] => -173.40700872797 [1] => -25.465001344078 ) [3] => Array ( [0] => -211.44500829533 [1] => -6.4740001788315 ) [4] => Array ( [0] => -209.93490817601 [1] => -3.255100166471 ) [5] =>
Array ( [0] => -190.0770099388 [1] => -13.202000524885 ) [6] => Array ( [0] => -171.92300716209 [1] => -22.296000898041 ) [7] => Array ( [0] => -172.13500940166 [1] => -22.749000947663 ) [8] => Array ( [0] => -171.12900859213 [1] => -23.251001225378 ) [9] => Array ( [0] => -152.49300807866 [1] => -32.559001622754 ) [10] => Array ( [0] => -133.92170714209 [1] => -41.834100838885 ) )
So far so good. It respects the format from example. But in the DXF file does write only 1 (from array number).
If I change the code in
$d->append(new DxfPolyLine(array('points'=>array($g[3]),
with array[3] - it does write the coordinates in DXF file. Is there a way to make php to read all arrays from an array? I've tried with foreach but it doesn't work. PHP gives an error for not closing the ).
The source code is here:
https://github.com/digitalfotografen/DXFwriter
With $g[3] I have the coordinates from array[3] in DXF file:
VERTEX
8
0
6
CONTINUOUS
10
-211.445
20
-6.474
0
If I put $g simple I have:
VERTEX
8
0
6
CONTINUOUS
10
1.000
20
1.000
30
1.000
40
1.000
50
1.000
60
1.000
70
1.000
I recreated the $g array based on your dump. Does this outputs the desired DXF file?
$g = [[-133.92170714209, -41.834100838885],
[-135.19600658422, -44.558002415365],
[-173.40700872797, -25.465001344078],
[-211.44500829533, -6.4740001788315],
[-209.93490817601, -3.255100166471 ],
[-190.0770099388 , -13.202000524885],
[-171.92300716209, -22.296000898041],
[-172.13500940166, -22.749000947663],
[-171.12900859213, -23.251001225378],
[-152.49300807866, -32.559001622754],
[-133.92170714209, -41.834100838885]
];
$d->append(new DxfPolyLine(['points' => $g]));
regarding building the array, you could do something like this:
for ($z = 0; $z < $numar; $z+=2) {
$g[] = [$coord[$z]*3.527785,$coord[$z+1]*3.527785];
}
Your formatting's a bit screwy, but looking at the dumped array-data I see a single array who's values are arrays, that have 2 float values each. Note that Array[0] and Array[10] have the same values which may or may not be a problem for the lib.
Also, what's with the asterisks in the $d->append... logic?
Is there a way to make php to read all arrays from an array?
Yes, but PHP will impose some restrictions depending on the nature of the keys and values. See http://php.net/manual/en/language.types.array.php for more specific info as to how PHP treats arrays.
I've tried with foreach but it doesn't work. PHP gives an error for not closing the ).
Can you post the failing code please? What you describe is simply a formatting / syntax error and nothing to do with the data itself.

Formatting an array to order by specified unix timestamp in PHP

I have an array which has a timestamp consistently on [3] ( an example of the array data below)
I would like the array to be sorted using the timestamp. I've seen a few stackoverflow posts that apparently do this using two methods, array_multisort() and usort() but I've been unable to replicate either.
Here is what I've tried based on my own code:
Attempt 1 - I pass the array to usort, then attempt to take it apart with the foreach. Applying this method definitely changes the order of the results, but the dates seems to be no specific order (ascending, descending).
function sortArray($a1, $a2){
if ($a1[3] == $a2[3]) return 0;
return ($a1[3] > $a2[3]) ? -1 : 1;
}
usort($the_array, "sortArray");
foreach($the_array as $sh) {
$uid = $sh['uid'];
$username = $sh['username'];
$datetime = $sh['datetime'];
$type = $sh['type'];
echo "<p> $uid , $username, $datetime, $type </p>";
}
Attempt 2 - tried using array_multisor() which again gives me results in a different order but I don't understand what it is sorting by exactly.
foreach ($the_array as $key => $node) {
$timestamps[$key] = $node[3];
}
array_multisort($timestamps, SORT_ASC, $the_array);
//process the array with a foreach to show results
My theory here is that it isn't properly processing the unix timestamp and I'm not sure what I can do about that. Is it smart to take out all the characters of the timestamp so it is a simple line of numbers ( 2014-01-02 03:02:12 becomes 20140102030212 )? Or is there another way to process it with the timestamp in it's current form?
Here is an example of the data in the array:
Array
(
[0] => Array
(
[uid] => 20013
[0] => 20013
[username] => myhipswontlie
[1] => myhipswontlie
[rating] => 4.00
[2] => 4.00
[datetime] => 2014-01-27 23:40:56
[3] => 2014-01-27 23:40:56
[type] => rated
[4] => rated
)
[1] => Array
(
[uid] => 20025
[0] => 20025
[username] => brasilchika
[1] => brasilchika
[rating] => 4.00
[2] => 4.00
[datetime] => 2014-01-02 03:02:12
[3] => 2014-01-02 03:02:12
[type] => rated
[4] => rated
)
[2] => Array
(
[uid] => 10002
[0] => 10002
[username] => crtten
[1] => crtten
[datetime] => 2014-01-25 01:33:34
[2] => 2014-01-25 01:33:34
[type] => visits
[3] => visits
)
)
Your issue is your numeric keys don't seem to match up in your arrays. Sometimes the datetime is found in the 3rd key, sometime it is found in the second key (which is odd considering they look like they come from mysql_fetch_array() which will make uniform arrays).
To solve this you should use the associative array key instead:
function sortArray($a1, $a2){
if ($a1['datetime'] == $a2['datetime']) return 0;
return ($a1['datetime'] > $a2['datetime']) ? -1 : 1;
}
usort($the_array, "sortArray");

help using php explode () and organizing output

Can someone pls show me how to map this correctly? I am trying to understand how to use php explode() and organizing the values in a way that I can retrieve and print them in some organized matter. For each record I want to put a name=value in a particular bucket. I have (7) max buckets per record. Sometimes I have records that won't fill each bucket.
(for example record (2) is missing attributes (5,6,7) and record (3) is missing attribute (4)).
1-Column=host1.colo.sub;2-Column=Fri Aug 13;3-Column=db9.nfl.colo2.;4-Column=00:00:03;5-Column=01:55:02;6-Column=87.24 MB;7-Column=Success;
1-Column=host1.colo.sub;2-Column=Fri Aug 13;3-Column=pdb2.colo2.;4-Column=04:00:02;
1-Column=host1.colo.sub;2-Column=Fri Aug 13;3-Column=gl3_lvm;5-Column=04:48:06;6-Column=54.64 MB;7-Column=Success;
So far I wrote this to view my output:
<?php
$InputFile = file("test.txt");
foreach ($InputFile as $line){
$pieces = explode(";", $line);
//print $pieces[0];
//print $pieces[1];
//print $pieces[2];
print $pieces[3];
//print $pieces[4];
//print $pieces[5];
//print $pieces[6];
//print_r($line);
}
?>
I would like to print out similar values for each attribute instead of this where its mixed.
Using 'print $pieces[3];'
4-Column=00:00:034-Column=04:00:025-Column=04:48:06
$InputFile = file("test.txt");
foreach ($InputFile as $line){
preg_match('~(1-Column[^;]*;?)?(2-Column[^;]*)?;?(3-Column[^;]*)?;?(4-Column[^;]*)?;?(5-Column[^;]*)?;?(6-Column[^;]*)?;?(7-Column[^;]*)?;?~',$line,$pieces);
$pieces = array_pad($pieces,8,'');
echo "<pre>";print_r($pieces);echo "</pre>";
}
output:
Array
(
[0] => 1-Column=host1.colo.sub;2-Column=Fri Aug 13;3-Column=db9.nfl.colo2.;4-Column=00:00:03;5-Column=01:55:02;6-Column=87.24 MB;7-Column=Success;
[1] => 1-Column=host1.colo.sub;
[2] => 2-Column=Fri Aug 13
[3] => 3-Column=db9.nfl.colo2.
[4] => 4-Column=00:00:03
[5] => 5-Column=01:55:02
[6] => 6-Column=87.24 MB
[7] => 7-Column=Success
)
Array
(
[0] => 1-Column=host1.colo.sub;2-Column=Fri Aug 13;3-Column=pdb2.colo2.;4-Column=04:00:02;
[1] => 1-Column=host1.colo.sub;
[2] => 2-Column=Fri Aug 13
[3] => 3-Column=pdb2.colo2.
[4] => 4-Column=04:00:02
[5] =>
[6] =>
[7] =>
)
Array
(
[0] => 1-Column=host1.colo.sub;2-Column=Fri Aug 13;3-Column=gl3_lvm;5-Column=04:48:06;6-Column=54.64 MB;7-Column=Success;
[1] => 1-Column=host1.colo.sub;
[2] => 2-Column=Fri Aug 13
[3] => 3-Column=gl3_lvm
[4] =>
[5] => 5-Column=04:48:06
[6] => 6-Column=54.64 MB
[7] => 7-Column=Success
)
If your input data is so irregular you would either need to parse it with a bit more code, not just a simple explode, or prepare it so that it works as expected with explode.
In the second case, you could use strpos to find all ";" characters in the string and check if the number after them is in order. If one (or more) number was skipped you should compensate by inserting another ";". This way explode will create an empty array element and all your resulting arrays should be aligned.
While it's not exactly clear what you're trying to accomplish, hopefully this code might help you figure out what's going on.
Note that here, I've added another loop inside the main foreach, to iterate over each name/value pair in the line:
<?php
$InputFile = file("test.txt");
$lineCnt = 0;
foreach ($InputFile as $line){
$lineCnt++;
echo "Processing line #" . $lineCnt. "\n";
$pieces = explode(";", $line);
foreach($pieces as $pair){
$pair = explode('=',$pair);
if (!empty($pair[1])){
print "\t".$pair[0] .' = ' . $pair[1] . "\n";
}
}
}
The script will produce nice-looking output if run from the command-line. If you're running it in the browser, you might want to change the \n's to , and the \t's to or something.
See if this helps...
$splits = explode(';',$_POST['data']);
foreach($splits as $id => $item) {
preg_match('/(.*?)=(.*)/',$item, $matches);
$parts[$matches[1]][] = $matches[2];
}
print_r($parts);
This will give you an array with keys as 1-Column, 2-Column as so on which will contain an array of related value. You can print this array in whatever way you want.
Here is the output:
[1-Column] => Array
(
[0] => host1.colo.sub
[1] => host1.colo.sub
[2] => host1.colo.sub
)
[2-Column] => Array
(
[0] => Fri Aug 13
[1] => Fri Aug 13
[2] => Fri Aug 13
)
[3-Column] => Array
(
[0] => db9.nfl.colo2.
[1] => pdb2.colo2.
[2] => gl3_lvm
)
[4-Column] => Array
(
[0] => 00:00:03
[1] => 04:00:02
)
[5-Column] => Array
(
[0] => 01:55:02
[1] => 04:48:06
)
[6-Column] => Array
(
[0] => 87.24 MB
[1] => 54.64 MB
)
[7-Column] => Array
(
[0] => Success
[1] => Success
)

Categories