I tried comparing 2 text files with data separated by -, in one case one file gets all data and in another case only has the data for change with the same id in this case this file it's called db_tmp.txt
The structure in both files it's this :
File txt ( the first it´s the id ) db/text.txt
1a34-Mark Jhonson
1a56-Jhon Smith
1a78-Mary Walter
The file for comparing, has for example the data for change, same id but different content - db_tmp.txt
1a56-Tom Tom
I created a function for comparing both files to detect if the same id and change exists:
<?php
$cron_file = file("db_tmp.txt");
$cron_compare = file("db/test.txt");
function cron($file_temp, $file_target)
{
for ($fte = 0; $fte < sizeof($file_temp); $fte++) {
$exp_id_tmp = explode("-", $file_temp[$fte]);
$cr_temp[] = "" . $exp_id_tmp[0] . "";
}
for ($ftt = 0; $ftt < sizeof($file_target); $ftt++) {
$exp_id_targ = explode("-", $file_target[$ftt]);
$cr_target[] = "" . $exp_id_targ[0] . "";
}
$diff = array_diff($cr_target, $cr_temp);
$it = 0;
foreach ($diff as $diff2 => $key) {
echo $diff2;
echo "--- $key";
print "<br>";
}
}
cron($cron_file, $cron_compare);
?>
If the same id exists in tmp, i must detect the entry in the other file and change to the value of the tmp, i try but can't get this to work, the function works but not for everything, if anyone can help me, that would be perfect, because i don´t know how continue this and save.
If you want to match according to id, a simple foreach would suffice, then just check during the loop if they have the same key. Consider this example:
// sample data from file('db_text.txt');
$contents_from_text = array('1a34-Mark Jhonson','1a56-Jhon Smith', '1a87-Mary Walter');
// reformat
$text = array();
foreach($contents_from_text as $element) {
list($key, $value) = explode('-', $element);
$text[$key] = $value;
}
$tmp = array();
// sample data from file('db_tmp.txt');
$contents_from_tmp = array('1a56-Tom Tom', '1a32-Magic Johnson', '1a23-Michael Jordan', '1a34-Larry Bird');
foreach($contents_from_tmp as $element) {
list($key, $value) = explode('-', $element);
$tmp[$key] = $value;
}
// compare
foreach($tmp as $key => $value) {
foreach($text as $index => $element) {
if($key == $index) {
$tmp[$key] = $element;
}
}
}
$contents_from_tmp = $tmp;
print_r($contents_from_tmp);
Sample Output
Related
I have an array like this:
$aMyArray = array(
"bmw"=>"user1",
"audi"=>"user2",
"mercedes"=>"user3"
);
And I only want to show the first two elements bmw=>user1 and audi=>user2.
But I want it by using a foreach loop.
If you want the first 2 by name:
Using in_array (documentation) is what you looking for:
$aMyArray = array("bmw"=>"user1", "audi"=>"user2", "mercedes"=>"user3");
$valuesToPrint = array("bmw", "audi");
foreach($aMyArray as $key => $val) {
if (in_array($key, $valuesToPrint))
echo "Found: $key => $val" . PHP_EOL;
}
If you want the first 2 by index use:
init index at 0 and increment in each iteration as:
$aMyArray = array("bmw"=>"user1", "audi"=>"user2", "mercedes"=>"user3");
$i = 0;
foreach($aMyArray as $key => $val) {
echo "Found: $key => $val" . PHP_EOL;
if (++$i > 1)
break;
}
$counter = 1;
$max = 2;
foreach ($aMyArray as $key => $value) {
echo $key, "=>", $value;
$counter++;
if ($counter === $max) {
break;
}
}
It is important to break execution to avoid arrays of any size looping until the end for no reason.
<?php
$aMyArray = array(
"bmw"=>"user1",
"audi"=>"user2",
"mercedes"=>"user3"
);
reset($aMyArray);
echo key($aMyArray).' = '.current($aMyArray)."\n";
next($aMyArray);
echo key($aMyArray).' = '.current($aMyArray)."\n";
Easiest way:
$aMyArray=array("bmw"=>"user1","audi"=>"user2","mercedes"=>"user3");
$i=0;
foreach ($aMyArray as $key => $value) {
if($i<2)
{
echo $key . 'and' . $value;
}
$i++;
}
I know you're asking how to do it in a foreach, but another option is using array travelling functions current and next.
$aMyArray = array(
"bmw"=>"user1",
"audi"=>"user2",
"mercedes"=>"user3"
);
$keys = array_keys($aMyArray);
//current($array) will return the value of the current record in the array. At this point that will be the first record
$first = sprintf('%s - %s', current($keys), current($aMyArray)); //bmw - user1
//move the pointer to the next record in both $keys and $aMyArray
next($aMyArray);
next($keys);
//current($array) will now return the contents of the second element.
$second = sprintf('%s - %s', current($keys), current($aMyArray)); //audi - user2
You are looking for something like this
$aMyArray = array(
"bmw"=>"user1",
"audi"=>"user2",
"mercedes"=>"user3"
);
foreach($aMyArray as $k=>$v){
echo $v;
if($k=='audi'){
break;
}
}
I have my source code here:
$title = "news1";
$a = array();
foreach($page_news as $keys=>$news) // this comes from controller including news1.
{
$x[] = $news->title;
$x[] .= $news->url;
}
// I want to get the index of matches where $x[values = "news1"]
$key_title = array_search($title,$a);
Then my question is : if I get the index of news->title, how can I get the correspondent index of $news->url?
As you always add the url after the title, you could simply add one to the index of your title to get the index of the url.
$title = "news1";
$a = array();
foreach($page_news as $keys=>$news) {
$x[] = $news->title;
$x[] = $news->url;
}
$key_title = array_search($title, $a);
$key_url = $key_title + 1;
A better way would be to use a multi dimensional array and use the title as the key - in this way, you don't need array_search
$a = array();
foreach($page_news as $keys=>$news) {
$x[$news->title] = [
'title' => $news->title,
'url' => $news->url
];
}
$entry = $a[$title];
echo $entry['title'];
echo $entry['url'];
Here is some idea to achieve it :
1/ Create an associative array for each title + url :
$title = "news1";
$a = array();
foreach($page_news as $keys = >$news)
{
$a[] = array(
'title' => $news->title,
'url' => $news->url
}
Then to find the key of $title :
foreach ($a as $key => $data) {
if ($data['title'] == $title) {
$key_title = $key;
}
}
Then echo $key_title will give you the key.
If you want to avoid the foreach loop, I recommand you to do what Phillip suggest : add the title as key.
2/ If you know the title you want to search before the first foreach loop (in your example you have the title before), maybe you can get it in this loop :
$title = "news1";
$a = array();
$key = 0;
foreach($page_news as $keys => $news)
{
$a[$key] = $news->title;
if ($news->title == $title) {
$key_title = $key;
}
$key++;
$a[$key] = $news->url;
$key++;
}
Then echo $key_title will give you the key and echo $key_title + 1 will give the key of the associated url.
3/ And third idea is to do what the anwser if Philipp suggest with :
$key_title = array_search($title, $a);
$key_url = $key_title + 1;
If your using PHP 7+, you can use array_column to convert the data into an indexed list of objects...
$indexed = array_column($page_news, null, "title");
echo "url=".$indexed[$title]->url;
BUT if you don't need this data for anything else, you would be better off doing a simple foreach and compare it against each item. This saves converting and storing all of the data which isn't used later ...
$url = "";
foreach ( $page_news as $news ) {
if ( $news->title = $title ) {
$url = $news->url;
break;
}
}
echo "url=".$url.PHP_EOL;
(this works in most versions of PHP)
$array['a:b']['c:d'] = 'test';
$array['a:b']['e:f']= 'abc';
I need output like below. array can have multiple level . Its comes with api so we do not know where colon come.
$array['ab']['cd'] = 'test';
$array['ab']['ef']= 'abc';
(untested code) but the idea should be correct if want to remove ':' from keys:
function clean_keys(&$array)
{
// it's bad to modify the array being iterated on, so we do this in 2 steps:
// find the affected keys first
// then move then in a second loop
$to_move = array();
forach($array as $key => $value) {
if (strpos($key, ':') >= 0) {
$target_key = str_replace(':','', $key);
if (array_key_exists($target_key, $array)) {
throw new Exception('Key conflict detected: ' . $key . ' -> ' . $target_key);
}
array_push($to_move, array(
"old_key" => $key,
"new_key" => $target_key
));
}
// recursive descent
if (is_array($value)) {
clean_keys($array[$key]);
}
}
foreach($to_move as $map) {
$array[$map["new_key"]] = $array[$map["old_key"]];
unset($array[$map["old_key"]]);
}
}
try this:
$array=array();
$array[str_replace(':','','a:b')][str_replace(':','','c:d')]="test";
print_r($array);
This seems like the simplest and most performant approach:
foreach ($array as $key => $val) {
$newArray[str_replace($search, $replace, $key)] = $val;
}
I have a list of IDs
$Ids="1201,1240,1511,1631,1663,1666,1716,2067,2095";
and in the /imgs/ folder there are many jpg filenames related to these IDs. But there are a lot of IDs that do not have any image.
for example there are in the /imgs/
1201_73.jpg
1201_2897.jpg
1240-9834.jpg
1240-24.jpg
1511-dsc984.jpg
1511-dsc34.jpg
What I want to achieve is to find which of the IDs have images in the img folder.
Thank you
Updated
$array = array();
$foo = explode('.jpg', $images);
foreach($foo as $id) {
$digi = substr(trim($id), 0,4);
if(!in_array($digi, $array)) {
array_push($array, $digi);
echo $id . ".jpg <br/>";
$where .= "id='$digi' or ";
}
}
First, turn your string of IDs into an array.
$idsArray = explode(',', $Ids);
Now iterate through the directory, checking each file to see if it starts with the ID.
$hasImages = array();
foreach (new DirectoryIterator(__DIR__ . '/imgs') as $fileInfo) {
if ($fileInfo->isDot() || $fileInfo->isDir()) {
continue;
}
foreach ($idsArray as $id) {
if (0 === strpos($fileInfo->getBasename(), $id)) {
$hasImages[] = $id;
break;
}
}
}
$hasImages = array_unique($hasImages);
$hasImages will contain an array of IDs which have an image.
Something like this should work:
$files = glob('/imgPath/*.jpg');
$hasImage = array_unique(array_map(function($file) {
return explode('-', $file)[0];
}, $files));
$withimages= array_diff(explode($Ids), $hasImage);
For example:
$arr = array(3,5,2,5,3,9);
I want to show only common elements i.e 3,5 as output.
Here's my attempt:
<?php
$arr = array(3,5,2,5,3,9);
$temp_array = array();
foreach($arr as $val)
{
if(isset($temp_array[$val]))
{
$temp_array[$val] = $val;
}else{
$temp_array[$val] = 0;
}
}
foreach($temp_array as $val2)
{
if($val2 > 0)
{
echo $val2 . ', ';
}
}
?>
--
Output --
3, 5,
Try the following:
$arr = array(3,5,2,5,3,9);
foreach($arr as $key => $val){
//remove the item from the array in order
//to prevent printing duplicates twice
unset($arr[$key]);
//now if another copy of this key still exists in the array
//print it since it's a dup
if (in_array($val,$arr)){
echo $val . " ";
}
}
Output:
3 5
Addition:
I guess that the reason you were asked to implement it yourself (without using built-in functions) was to avoid answers like:
$unique = array_unique($arr);
$dupes = array_diff_key( $arr, $unique );
$arrnew = array();
for($i=0;$i<count($arr);$i++)
{
for($j=$i+1;$j<count($arr);$j++)
{
if($arr[$i]==$arr[$j])
{
$arrnew[]=$arr[$j];
}
}
}