Reputation: 43
I'm trying to add only last name if first name is same
data.txt
Alice Sandy
Alice Nanami
James Watt
Alice Monica
Johann Gauss
to result.txt
Alice Sandy Nanami Monica
James Watt
Johann Gauss
I try with this code
$resultFile = "result.txt";
$search = "Alice";
$lineNumber = false;
if ($handle = fopen($result, "r")) {
$count = 0;
while (($line = fgets($handle, 4096)) !== FALSE and !$lineNumber) {
$count++;
$lineNumber = (strpos($line, $search) !== FALSE) ? $count : $lineNumber;
$isExist = (strpos($line, $search) !== FALSE) ? "yup" : "no";
}
fclose($handle);
}
if($isExist=="yup"){
$lines = file($resultFile);
$lines[$lineNumber] = $lines[$lineNumber].' '.$lastName;
file_put_contents($result, implode('', $lines));
}else{
$fullName = $firstName.' '.$lastName;
$fileOpen = fopen($result, "a");
fwrite($fileOpen,$fullName);
fclose($fileOpen);
$addBreaker = "\n";
$splResult = new SplFileObject($resultFile, 'a');
$splResult->fwrite($addBreaker);
}
But it give error offset (I'm using PHP 7) and the result is untidy
Alice Sandy Nanami
Monica
James Watt
Johan Gauss
Thanks for help
Upvotes: 1
Views: 126
Reputation: 47874
Use file()
to collect the file contents as an array of lines. My snippet starts from there with $lines
.
Iterate the array and makes each line modifiable by reference. (&
)
Locate the first occurring needle match that not only exists in the line but matches the whole first word so that you don't get false-positive matching.
Then declare the first match as a reference variable (=&
) and continue iterating the array. Any subsequent matches will have the delimiting space and second word appended to the reference variable. Then immediate unset the line to be purged from the document.
When done, re-implode the data and stuff the content into the result file.
This is clean, readable, and only needs one loop.
Code: (Demo)
// $lines = file('result.txt', FILE_IGNORE_NEW_LINES);
$lines = [
'Alice Sandy',
'Alice Nanami',
'James Watt',
'Alice Monica',
'Johann Gauss',
'Cooper Alice',
];
$needle = 'Alice';
foreach($lines as $index => &$line) {
if ($needle === strstr($line, ' ', true)) { // check whole first word
if (!isset($firstOccurrence)) {
$firstOccurrence =& $line;
} else {
$firstOccurrence .= strstr($line, ' ');
unset($lines[$index]);
}
}
}
var_export($lines);
// file_put_contents('result.txt', implode(PHP_EOL, $lines));
Output:
array (
0 => 'Alice Sandy Nanami Monica',
2 => 'James Watt',
4 => 'Johann Gauss',
5 => 'Cooper Alice',
)
P.s if you want to know if any rows were changed you could check if the original array is ===
the new array after looping, or you could just use a boolean flag variable in the else
condition.
Upvotes: 0
Reputation: 10572
Another apporach instead of replacing lines would be save every line to an array and then iterate over array and save to the new file. You can also use the same file as an $outputFile
.
$inputFile = 'names.txt';
$outputFile = 'result.txt';
$names = [];
if ($handle = fopen($inputFile, "r")) {
$count = 0;
while (($line = fgets($handle, 4096)) !== FALSE) {
$count++;
$lineNames = explode(' ', $line);
$names[$lineNames[0]][] = trim($lineNames[1]);
}
fclose($handle);
}
$handle = fopen($outputFile, 'w');
foreach ($names as $firstName => $lastNames) {
fwrite($handle, $firstName . ' ' . implode(' ', $lastNames) . PHP_EOL);
}
Two additional notes:
Don't use string as boolean value.
$isExist = (strpos($line, $search) !== FALSE) ? "yup" : "no";
Use just following condition. It's enough
$isExist = (strpos($line, $search) !== FALSE)
Upvotes: 1