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;
}
}
}
}
?>
Related
I have a string like this:-
$a = " [abc,hjhd],[ccdc,cdc],[csc,vdfv]";
I want to insert this string into an array.
$marker_tower_line = array(
'type' => 'Feature',
'properties' => array(
'marker-color' => '#f00',
'marker-size' => 'small'
),
'geometry' => array(
'type' => 'LineString',
'coordinates' => array (
$a
)
)
);
The output coming is-
["[abc,hjhd],[ccdc,cdc],[csc,vdfv]"];
But I need-
[[abc,hjhd],[ccdc,cdc],[csc,vdfv]];
The most Simplest answer (one-liner with simple php functions):-
<?php
$a = " [abc,hjhd],[ccdc,cdc],[csc,vdfv]";
$b = array_chunk(explode(",",str_replace(array("[","]"),array("",""),trim($a))),2);
print_r($b);
Output:- https://eval.in/833862
Or a bit more shorten (without trim()):-
<?php
$a = " [abc,hjhd],[ccdc,cdc],[csc,vdfv]";
$b = array_chunk(explode(",",str_replace(array("[","]"," "),array("","",""),$a)),2);
print_r($b);
Output:- https://eval.in/833882
i think you are looking for this,
$somearray=explode(",",$a);
then use $somearray for coordinates. The only catch is that you have to use this idea to implement in your logic.For example if $a is the string that you are making then make it like this,
$a = "[abc,hjhd].,[ccdc,cdc].,[csc,vdfv]";
and then use explode as
$somearray=explode(".,",$a);
hope this helps.
You can use this code. The function make_my_array() will work for any string encoded in your given format.
The make_my_array() function takes your string as parameter and iterates through every character to make your output array. It determines staring of a set by '[' character and determines separate set elements by ',' character and the ']' character determines end of a set.
function make_my_array($sa) {
$s = "";
$ans = array();
for($i=0; $i<strlen($sa); $i++) {
$t = array();
if($sa[$i] == '[') {
for($j=$i+1; $j<strlen($sa); $j++) {
if($sa[$j] == ',') {
$t[] = $s;
$s = "";
}
else if($sa[$j] == ']') {
$t[] = $s;
$s = "";
$i = $j + 1;
$ans[] = $t;
break;
}
else {
$s .= $sa[$j];
}
}
}
}
return $ans;
}
$a = " [abc,hjhd],[ccdc,cdc],[csc,vdfv]";
$marker_tower_line = array(
'type' => 'Feature',
'properties' => array(
'marker-color' => '#f00',
'marker-size' => 'small'
),
'geometry' => array(
'type' => 'LineString',
'coordinates' => make_my_array($a)
)
);
I have a loop that builds an array of associative arrays that looks like this:
array(
'foo' => '',
'bar' => '',
'thingys' => array()
)
on each iteration of the loop, I want to search through the array for an associate array that's 'foo' and 'bar' properties match those of the current associate array. If it exists I want to append the thingys property of the current associative array to the match. Otherwise append the entire thing.
I know how to do this with for loops, but I'm wondering if there is a simpler way to do this with an array function. I'm on php 5.3.
Example
<?php
$arr = array(
array(
'foo' => 1,
'bar' => 2,
'thing' => 'apple'
),
array(
'foo' => 1,
'bar' => 2,
'thing' => 'orange'
),
array(
'foo' => 2,
'bar' => 2,
'thing' => 'apple'
),
);
$newArr = array();
for ($i=0; $i < count($arr); $i++) {
$matchFound = false;
for ($j=0; $j < count($newArr); $j++) {
if ($arr[$i]['foo'] === $newArr[$j]['foo'] && $arr[$i]['bar'] === $newArr[$j]['bar']) {
array_push($newArr[$j]['thing'], $arr[$i]['things']);
$matchFound = true;
break;
}
}
if (!$matchFound) {
array_push($newArr,
array(
'foo' => $arr[$i]['foo'],
'bar' => $arr[$i]['bar'],
'things' => array($arr[$i]['thing'])
)
);
}
}
/*Output
$newArr = array(
array(
'foo' => 1,
'bar' => 2,
'things' => array('orange', 'apple')
),
array(
'foo' => 2,
'bar' => 2,
'things' => array('apple')
),
)
*/
?>
I don't know if it is possible through a built-in function, but I think no. Something can be implemented through array_map, but anyway you have to perform a double loop.
I propose you a one-loop solution using a temporary array ($keys) as index of already created $newArr items, based on foo and bar; elements of original array are processed through a foreach loop, and if a $keys element with first key as foo value and second key as bar value exists, then the current thing value is added to the returned key index of $newArr, otherwise a new $newArray element is created.
$newArr = $keys = array();
foreach( $arr as $row )
{
if( isset( $keys[$row['foo']][$row['bar']] ) )
{ $newArr[$keys[$row['foo']][$row['bar']]]['thing'][] = $row['thing']; }
else
{
$keys[$row['foo']][$row['bar']] = array_push( $newArr, $row )-1;
$newArr[$keys[$row['foo']][$row['bar']]]['thing'] = array( $row['thing'] );
}
}
unset( $keys );
3v4l.org demo
Edit: array_map variant
This is the same solution above, using array_map instead of foreach loop. Note that also your original code can be converted in this way.
$newArr = $keys = array();
function filterArr( $row )
{
global $newArr, $keys;
if( isset( $keys[$row['foo']][$row['bar']] ) )
{ $newArr[$keys[$row['foo']][$row['bar']]]['thing'][] = $row['thing']; }
else
{
$keys[$row['foo']][$row['bar']] = array_push( $newArr, $row )-1;
$newArr[$keys[$row['foo']][$row['bar']]]['thing'] = array( $row['thing'] );
}
}
array_map( 'filterArr', $arr );
3v4l.org demo
I expect array_combine to be able to take two arrays such as:
array('sample', 'sample_two', 'sample');
array(array('info', 'info_two'), array('bananas'), array('more_stuff'));
and produce:
array(
'sample' => array(
'info', 'info_two', 'more_stuff'
),
'sample_two' => array(
'bananas'
)
);
instead I get:
array(
'sample' => array(
'more_stuff'
),
'sample_two' => array(
'bananas'
)
);
Now I know php doesn't allow for duplicate key's so how can I use array_combine or some other method to achieve the desired array? It is safe to say that, the first array, will always match the second array in terms of layout. So you can draw lines between the values of array one and array two.
Why not writing your own function?
function my_array_combine(array $keys, array $values) {
$result = array();
for ($i = 0; $i < count($keys); $i++) {
$key = $keys[$i];
if (!isset($result[$key])) {
$result[$key] = array();
}
$result[$key] = array_merge($result[$key], $values[$i]);
}
return $result;
}
I have a url http://*.com/branch/module/view/id/1/cat/2/etc/3.
It becomes.
array
(
'module'=>'branch',
'controller'=>'module',
'action'=>'view'
);
next I need to get the params.
Ihave this array.
/*function getNextSegments($n,$segments) {
return array_slice ( $q = $this->segments, $n + 1 );
}
$params = getNextSegments(3);
*/
array ( 0 => 'id', 1 => '1', 2 => 'cat', 3 => '2', 4 => 'etc', 5 => '3' );//params
And i wanna convert it to this one:
array
(
'id'=>1,
'cat'=>2,
'etc'=>3,
);
How i can do this using php function. I know I can do using for or foreach, but I think php has such function , but i cant find it :(.
Thank you.
class A {
protected function combine($params) {
$count = count ( $params );
$returnArray = array ();
for($i = 0; $i < $count; $i += 2) {
$g = $i % 2;
if ($g == 0 or $g > 0) {
if (isset ( $params [$i] ) and isset ( $params [$i + 1] ))
$returnArray [$params [$i]] = $params [$i + 1];
}
}
return $returnArray;
}
}
This works normaly. If anybody has better logic for this please help.
Thank you again.
PHP does not have a built-in function for this. I would just implement it with explode and a loop, shouldn't be that hard.
I use a function like this in my extended Zend_Controller_Action class.
public function getCleanParams()
{
$removeElements = array(
'module' => '',
'controller' => '',
'action' => '',
'_dc' => ''
);
return array_diff_key($this->_request->getParams(), $removeElements);
}
That will give you your parameters in a clean fashion and the format you want it in.
You can start building your router with the following regular expression (name the file index.php):
<?php
$pattern = '#^(?P<module>branch)/'.
'(?P<controller>module)/'.
'(?P<action>view)'.
'(:?/id[s]?/(?P<id>[0-9]+))?'.
'(:?/cat[s]?/(?P<cat>[0-9]+))?'.
'(:?/etc[s]?/(?P<etc>[0-9]+))?#ui';
preg_match($pattern, trim($_SERVER['REQUEST_URI'], '/'), $segment);
echo sprintf('<pre>%s</pre>', var_export($segment, true));
Assuming you have PHP 5.4.x installed, you can type the following on the command-line:
% php -S localhost:8765
Now browse to http://localhost:8765/branch/module/view/id/1/cat/2/etc/3
The output will be (removed numeric keys except 0 for clarity):
array (
0 => 'branch/module/view/id/1/cat/2/etc/3',
'module' => 'branch',
'controller' => 'module',
'action' => 'view',
'id' => '1',
'cat' => '2',
'etc' => '3',
)
As I was writing a for loop earlier today, I thought that there must be a neater way of doing this... so I figured I'd ask. I looked briefly for a duplicate question but didn't see anything obvious.
The Problem:
Given N arrays of length M, turn them into a M-row by N-column 2D array
Example:
$id = [1,5,2,8,6]
$name = [a,b,c,d,e]
$result = [[1,a],
[5,b],
[2,c],
[8,d],
[6,e]]
My Solution:
Pretty straight forward and probably not optimal, but it does work:
<?php
// $row is returned from a DB query
// $row['<var>'] is a comma separated string of values
$categories = array();
$ids = explode(",", $row['ids']);
$names = explode(",", $row['names']);
$titles = explode(",", $row['titles']);
for($i = 0; $i < count($ids); $i++) {
$categories[] = array("id" => $ids[$i],
"name" => $names[$i],
"title" => $titles[$i]);
}
?>
note: I didn't put the name => value bit in the spec, but it'd be awesome if there was some way to keep that as well.
Maybe this? Not sure if it's more efficient but it's definitely cleaner.
/*
Using the below data:
$row['ids'] = '1,2,3';
$row['names'] = 'a,b,c';
$row['titles'] = 'title1,title2,title3';
*/
$categories = array_map(NULL,
explode(',', $row['ids']),
explode(',', $row['names']),
explode(',', $row['titles'])
);
// If you must retain keys then use instead:
$withKeys = array();
foreach ($row as $k => $v) {
$v = explode(',', $v);
foreach ($v as $k2 => $v2) {
$withKeys[$k2][$k] = $v[$k2];
}
}
print_r($categories);
print_r($withKeys);
/*
$categories:
array
0 =>
array
0 => int 1
1 => string 'a' (length=1)
2 => string 'title1' (length=6)
...
$withKeys:
array
0 =>
array
'ids' => int 1
'names' => string 'a' (length=1)
'titles' => string 'title1' (length=6)
...
*/
Just did a quick simple benchmark for the 4 results on this page and got the following:
// Using the following data set:
$row = array(
'ids' => '1,2,3,4,5',
'names' => 'abc,def,ghi,jkl,mno',
'titles' => 'pqrs,tuvw,xyzA,BCDE,FGHI'
);
/*
For 10,000 iterations,
Merge, for:
0.52803611755371
Merge, func:
0.94854116439819
Merge, array_map:
0.30260396003723
Merge, foreach:
0.40261697769165
*/
Yup, array_combine()
$result = array_combine( $id, $name );
EDIT
Here's how I'd handle your data transformation
function convertRow( $row )
{
$length = null;
$keys = array();
foreach ( $row as $key => $value )
{
$row[$key] = explode( ',', $value );
if ( !is_null( $length ) && $length != count( $row[$key] ) )
{
throw new Exception( 'Lengths don not match' );
}
$length = count( $row[$key] );
// Cheap way to produce a singular - might break on some words
$keys[$key] = preg_replace( "/s$/", '', $key );
}
$output = array();
for ( $i = 0; $i < $length; $i++ )
{
foreach ( $keys as $key => $singular )
{
$output[$i][$singular] = $row[$key][$i];
}
}
return $output;
}
And a test
$row = convertRow( $row );
echo '<pre>';
print_r( $row );