php: How to assign an array's values to default table? - arrays

Here is my code:
$table=array("a","b","c","d");
$datas=array("a_1","c_8");
foreach($datas as $x => $data){
$data=explode("_",$data);
$keys[$x]=$data[0];
$vals[$x]=$data[1];
}
$key=implode("</td><td>",$keys);
$val=implode("</td><td>",$vals);
echo"<table><tr><td>".$key."</td></tr><tr><td>".$val."</td></tr></table>";
It prints out like this:
a c
1 8
But i want this one:
a b c d
1 8

Your problem is the foreach, it's currently only running 2 times, since the $datas Array only has two entrys. Try using the table Array, just like so:
$table=array("a","b","c","d");
$datas=array("a_1","c_8");
foreach($table as $x => $tab){
$var = "";
foreach($datas as $data){
$data = explode("_", $data);
if($data[0]==$tab){
$var = $data[1];
}
}
$keys[$x]=$tab;
$vals[$x]=$var;
}
$key=implode("</td><td>",$keys);
$val=implode("</td><td>",$vals);
echo"<table><tr><td>".$key."</td></tr><tr><td>".$val."</td></tr></table>";

Related

Powershell use values of one array as headings for another array

I have two arrays in Powershell:
$headings = ['h1', 'h2']
$values = [3, 4]
It is guaranteed that both arrays have the same length. How can I create an array where the values of $headings become the headings of the $values array?
I want to be able to do something like this:
$result['h2'] #should return 4
Update:
The arrays $headings and $values are of type System.Array.
As stated above you'll need a PowerShell hashtable. By the way array in PowerShell are defined via #(), see about_arrays for further information.
$headings = #('h1', 'h2')
$values = #(3, 4)
$combined = #{ }
if ($headings.Count -eq $values.Count) {
for ($i = 0; $i -lt $headings.Count; $i++) {
$combined[$headings[$i]] = $values[$i]
}
}
else {
Write-Error "Lengths of arrays are not the same"
}
$combined
Dumping the content of combined returns:
$combined
Name Value
---- -----
h2 4
h1 3
Try something like this :
$hash = [ordered]#{ h1 = 3; h2 = 4}
$hash["h1"] # -- Will give you 3
## Next Approach
$headings = #('h1', 'h2') #array
$values = #(3, 4) #array
If($headings.Length -match $values.Length)
{
For($i=0;$i -lt $headings.Length; $i++)
{
#Formulate your Hashtable here like the above and then you would be able to pick it up
#something like this in hashtable variable $headings[$i] = $values[$i]
}
}
PS: I am just giving you the logical headstart and helping you with the hashtable part. Code is upto you.

Is it possible to assign two variables in Perl foreach loop?

Is it possible to assign two variables the same data from an array in a Perl foreach loop?
I am using Perl 5, I think I came across something in Perl 6.
Something like this:
my $var1;
my $var2;
foreach $var1,$var2 (#array){...}
It's not in the Perl 5 core language, but List::Util has a pairs function which should be close enough (and a number of other pair... functions which may be more convenient, depending on what you're doing inside the loop):
#!/usr/bin/env perl
use strict;
use warnings;
use 5.010;
use List::Util 'pairs';
my #list = qw(a 1 b 2 c 3);
for my $pair (pairs #list) {
my ($first, $second) = #$pair;
say "$first => $second";
}
Output:
a => 1
b => 2
c => 3
The easiest way to use this is with a while loop that calls splice on the first two elements of the array each time,
while (my($var1, $var2) = splice(#array, 0, 2)) {
...
}
However, unlike foreach, this continually does a double-shift on the original array, so when you’re done, the array is empty. Also, the variables assigned are copies, not aliases as with foreach.
If you don’t like that, you can use a C-style for loop:
for (my $i = 0; $i < #array; $i += 2) {
my($var1, $var2) = #array[$i, $i+1];
...
}
That leaves the array in place but does not allow you to update it the way foreach does. To do that, you need to address the array directly.
my #pairlist = (
fee => 1,
fie => 2,
foe => 3,
fum => 4,
);
for (my $i = 0; $i < #pairlist; $i += 2) {
$pairlist[ $i + 0 ] x= 2;
$pairlist[ $i + 1 ] *= 2;
}
print "Array is #pairlist\n";
That prints out:
Array is feefee 2 fiefie 4 foefoe 6 fumfum 8
You can get those into aliased variables if you try hard enough, but it’s probably not worth it:
my #kvlist = (
fee => 1,
fie => 2,
foe => 3,
fum => 4,
);
for (my $i = 0; $i < #kvlist; $i += 2) {
our ($key, $value);
local(*key, $value) = \#kvlist[ $i, $i + 1 ];
$key x= 2;
$value *= 2;
}
print "Array is #kvlist\n";
Which prints out the expected changed array:
Array is feefee 2 fiefie 4 foefoe 6 fumfum 8
Note that the pairs offered by the List::Pairwise module, which were but very recently added to the core List::Util module (and so you probably cannot use it), are still not giving you aliases:
use List::Util 1.29 qw(pairs);
my #pairlist = (
fee => 1,
fie => 2,
foe => 3,
fum => 4,
);
for my $pref (pairs(#pairlist)) {
$pref->[0] x= 2;
$pref->[1] *= 2;
}
print "Array is #pairlist\n";
That prints out only:
Array is fee 1 fie 2 foe 3 fum 4
So it didn’t change the array at all. Oops. :(
Of course, if this were a real hash, you could double the values trivially:
for my $value (values %hash) { $value *= 2 }
The reasons that works is because those are aliases into the actual hash values.
You cannot change the keys, since they’re immutable. However, you can make a new hash that’s an updated copy of the old one easily enough:
my %old_hash = (
fee => 1,
fie => 2,
foe => 3,
fum => 4,
);
my %new_hash;
#new_hash{ map { $_ x 2 } keys %old_hash } =
map { $_ * 2 } values %old_hash;
print "Old hash is: ", join(" " => %old_hash), "\n";
print "New hash is: ", join(" " => %new_hash), "\n";
That outputs
Old hash is: foe 3 fee 1 fum 4 fie 2
New hash is: foefoe 6 fiefie 4 fumfum 8 feefee 2
A general algorithm for more than 2 variables:
while( #array ){
my $var1 = shift #array;
my $var2 = shift #array;
my $var3 = shift #array;
# other variables from #array
# do things with $var1, $var2, $var3, ...
}
PS: Using a working copy of the array to that it is preserved for use later:
if( my #working_copy = #array ){
while( #working_copy ){
my $var1 = shift #working_copy;
my $var2 = shift #working_copy;
my $var3 = shift #working_copy;
# other variables from #working_copy
# do things with $var1, $var2, $var3, ...
}
}
PPS: another way is to use indexing. Of course, that is a sure sign that the data structure is wrong. It should be an array of arrays (AoA) or an array of hashes (AoH). See perldoc perldsc and perldoc perllol.
my $i = 0;
while( $i < #array ){
my $var1 = $array[ $i++ ];
my $var2 = $array[ $i++ ];
my $var3 = $array[ $i++ ];
# other variables from #array
# do things with $var1, $var2, $var3, ...
}
PPPS: I've been asked to clarify why the data structure is wrong. It is a flatten set of tuples (aka records aka datasets). The tuples are recreated by counting of the number of data for each. But what is the reader constructing the set has a bug and doesn't always get the number right? If, for a missing value, it just skips adding anything? Then all the remaining tuples are shifted by one, causing the following tuples to be grouped incorrectly and therefore, invalid. That is why an AoA is better; only the tuple with the missing data would be invalid.
But an better structure would be an AoH. Each datum would access by a key. Then new or optional data can be added without breaking the code downstream.
While I'm at it, I'll add some code examples:
# example code for AoA
for my $tuple ( #aoa ){
my $var1 = $tuple->[0];
my $var2 = $tuple->[1];
my $var3 = $tuple->[2];
# etc
}
# example code for AoH
for my $tuple ( #aoh ){
my $var1 = $tuple->{keyname1};
my $var2 = $tuple->{key_name_2};
my $var3 = $tuple->{'key name with spaces'};
my $var4 = $tuple->{$key_name_in_scalar_variable};
# etc
}
Here is a module-less way to "loop" by an arbitrary value ($by) and output the resulting group of elements using an array slice:
#!perl -l
#array = "1".."6";
$by = 3; $by--;
for (my $i = 0 ; $i < #array ; $i += $by ) {
print "#array[$i..$i+$by]";
$i++ ;
}
As a one-liner to test (cut and paste to a Unix shell):
perl -E '#array = "1".."6"; $by = 3; $by--;
for (my $i = 0 ; $i < #array ; $i += $by ) {
say "#array[$i..$i+$by]"; $i++ }'
Output:
1 2 3
4 5 6
If you make $by = 2; it will print pairs of numbers. To get at specific elements of the resulting slice access it as an anonymous array: (e.g. [#array[$i..$i+$by]]->[1]).
See also:
How do I read two items at a time in a Perl foreach loop?
Perl way of iterating over 2 arrays in parallel
Some good responses there, including reference to natatime which is quite easy to use. It's easy to implement too - it is essentially a wrapper around the splice solutions mentioned in the responses here.
The following is not the nicest example, but I've been using autobox::Core and made an #array->natatime() "method" ;-) like this:
use autobox::Core ;
sub autobox::Core::ARRAY::natatime {
my ($self, $by) = #_;
my #copy = #$self ;
my #array ;
push #array, [splice (#copy, 0, $by) ] while #copy ;
if ( not defined wantarray ) {
print "#{ $_ } \n" for #array ;
}
return wantarray ? #array : \#array;
}
The #copy array is spliced destructively, but $self (which is how the #array in front of the autobox method -> arrow gets passed to the function) is still there. So I can do:
my #dozen = "1" .. "12" ; # cakes to eat
#dozen->natatime(4) ; # eat 4 at time
my $arr_ref = #dozen->natatime(4) ; # make a reference
say "Group 3: #{ $arr_ref->[2] }" ; # prints a group of elements
say scalar #dozen , " cakes left" ; # eat cake; still have it
Output:
1 2 3 4
5 6 7 8
9 10 11 12
Group 3: 9 10 11 12
12 cakes left
One other approach that also uses a CPAN module (I gave this answer elsewhere but it is worth repeating). This can also be done non-destructively, with Eric Strom's excellent List::Gen module:
perl -MList::Gen=":all" -E '#n = "1".."6"; say "#$_" for every 2 => #n'
1 2
3 4
5 6
Each group of elements you grab is returned in an anonymous array so the individual values are in: $_->[0] $_->[1] ... etc.
You mentioned Perl6, which handles multiple looping values nicely:
my #qarr = 1 .. 6;
my ($x, $y, $z) ;
for #qarr -> $x , $y , $z { say $x/$y ; say "z = " ~ $z }
Output:
0.5
z = 3
0.8
z = 6
For more on the Perl6 approach see: Looping for Fun and Profit from the 2009 Perl6 Advent Calendar, or the Blocks and Statements Synopsis for details. Perhaps Perl 5 will have a similar "loop by multliple values" construct one day - à la perl5i's foreach :-)

how to find the number of repeating strings and their array index in a string array in matlab

I have a long array (1x75000 !) of string data.
In this array, there are repeated strings.
i want to find the array indices and the number of each repeating string.
E.g.
A=['abc' 'efg' 'hij' 'abc' 'hij' 'efg' 'klm'];
the answer should be:
2 times 'abc' at array indices 1, 4
2 times 'efg' at array indices 2, 6
2 times 'hij' at array indices 3, 5
1 time 'klm' at array indices 7
notice the large size of the array (1x75000)
This code should work:
<?php
$array = array('abc','wrerwe','wrewer','abc');
$out = array();
foreach ($array as $key => $value) {
if (!isset($out[$value])) {
$out[$value]['nr'] = 0;
$out[$value]['index'] = array();
}
++$out[$value]['nr'] ;
$out[$value]['index'][] = $key;
}
foreach ($out as $k => $v) {
echo "item ".$k." repeats ".$v['nr'].' times at positions: ';
echo implode(', ', $v['index']);
echo "<br />";
}
But so far I haven't tested in on such big array. In fact I don't think you should operate on such big arrays. You should rather divide it on smaller arrays.
I've tested it on 75000 array using code ( source for generating random string from How to create a random string using PHP? ) :
<?php
$array = randomTexts(75000);
$out = array();
foreach ($array as $key => $value) {
if (!isset($out[$value])) {
$out[$value]['nr'] = 0;
$out[$value]['index'] = array();
}
++$out[$value]['nr'] ;
$out[$value]['index'][] = $key;
}
foreach ($out as $k => $v) {
echo "item ".$k." repeats ".$v['nr'].' times at positions: ';
echo implode(', ', $v['index']);
echo "<br />";
}
function randomTexts($nr) {
$out = array();
$validString = 'abddefghihklmnopqrstuvwzyx';
for ($i=0; $i< $nr; ++$i) {
$len = mt_rand(5,10);
$out[] = get_random_string($validString, $len);
}
return $out;
}
function get_random_string($valid_chars, $length)
{
// start with an empty random string
$random_string = "";
// count the number of chars in the valid chars string so we know how many choices we have
$num_valid_chars = strlen($valid_chars);
// repeat the steps until we've created a string of the right length
for ($i = 0; $i < $length; $i++)
{
// pick a random number from 1 up to the number of valid chars
$random_pick = mt_rand(1, $num_valid_chars);
// take the random character out of the string of valid chars
// subtract 1 from $random_pick because strings are indexed starting at 0, and we started picking at 1
$random_char = $valid_chars[$random_pick-1];
// add the randomly-chosen char onto the end of our string so far
$random_string .= $random_char;
}
// return our finished random string
return $random_string;
}
It also seems to work but it takes a few seconds

php: rename duplicate keys by giving number in foreach

i have a form data and the data's array like this:
$datas=array("x-1","y-2","y-2","y-3","t-1");
my foreach loop:
foreach($datas as $x => $data){
$data=explode("-",$data);
if($data[0]==$data[0]+1){$n=1;}else{$n=0;}
$keys[$x]=$data[0].$n++;
$vals[$x]=$data[1];
}
i couldn't write the true code, my 3rd line is wrong i think (if($data[0]=$data[0]+1){$n="1";}else{$n="";})
so, i wanna rename the duplicate keys by giving number. my output should be like this:
x=1 y1=1 y2=2 y3=2 t1=1
Try
$datas=array("x-1","y-2","y-2","y-3","t-1");
$i=0;
$n=1;
foreach($datas as $x => $data){
$data=explode("-",$data);
$data2=explode("-",$datas[$i+1]);
if($data[0]==$data2[0])
{
$keys[$x]=$data[0].$n;
$n=$n+1;
}
else
{
$keys[$x]=$data[0].$n;
$n=0;
}
$vals[$x]=$data[1];
$i++;
}
This code has error you use = Which will assign value , not compare it.
also n should be integer not string
To fix that
foreach($datas as $x => $data){
$data=explode("-",$data);
if($keys[$x]==$keys[$x+1]){$n=1;}else{$n=0;}
$keys[$x]=$data[0].$n++;
$vals[$x]=$data[1];
}
if($data[0]=$data[0]+1){$n="1";}else{$n="";}
Use == instead of = for the if statements

How is it possible to echo a multidimension array value witout loop in php

I have a multidimension array, in fact a 2 dimension array, I like to echo all the value of the second index... something like that : $cars[0][0]
$cars = array
(
array("Volvo",100,96),
array("BMW",60,59),
array("Toyota",110,100)
);
$cars[0][0] will get me : Volvo. what i need is : Volvo 100 96. Is there is a way to echo this ?.. not print_r or var_dump. does a php function exist to do that ?
let's say now the RESULT array is $cars... 3 sub array value... i what them out. based on answer i try that :
foreach ($cars as $singleArray => $key) {
$result = "";
$result = implode(' ', $singleArray[$key]);
echo '# '. $key .' '. $result .'<br/>';
}
there is an ERROR : Warning: implode() [function.implode]: Invalid arguments passed in /home/studiot/public_html/previsite.com/data/array2.php on line 46
Array
i have done it like this :
foreach ($cars as $singleArray) {
$keyValue ++;
$result = "";
$result .= implode(' ', $singleArray);
echo '(# '. $keyValue .') -> '. $result .'<br/>';
}
You can simply implode the array you want to output with spaces:
echo implode(' ', $cars[0]);
// Volvo 100 96
Docs: http://nz1.php.net/function.implode
EDIT
I see you've tried to use a foreach loop, your syntax is wrong for it. foreach parameters are input array as array key => array value. So you'll implode the value (which is another array. Like this:
foreach ($cars as $key => $value) {
$result = implode(' ', $value);
echo '# '. $key .' '. $result .'<br/>';
}

Resources