我有类似这个字符串数组的东西,因为它们非常相似,但字符串中的同一个地方除外:
$array = [
'1',
'2',
'3',
'4',
'5',
...
];
// And preferrably
$string = 'This is +%s% better than last time!';
从此我想结束
var a, b;
var index = Math.random();
if (index < 0.5) {
// operate on a
var firstVId = '4L5g2kN9oUU';
} else {
// operate on b
var firstVId = '6Z1y3b46A1k';
}
通过一个函数,它接受任何类似字符串的数组并输出实际上不同的字符串。
答案 0 :(得分:1)
function myfunc($strings) {
// if the array is empty we don't have anything to do
if (count($strings) == 0) return "";
// count how many words are in a string (use the first one)
$num_tokens = 0;
$tok = strtok($strings[0], " ");
while ($tok !== false) {
$num_tokens++;
$tok = strtok(" ");
}
$output = "";
$tokens = [];
// iterate over each word of the string
for ($w = 0; $w < $num_tokens; $w++) {
// iterate over each string
for ($s = 0; $s < count($strings); $s++) {
// extract the same word of each string
$tokens[$s] = strtok($strings[$s], " ");
// remove that word from the string so it
// will not be extracted again
$strings[$s] = trim(substr($strings[$s], strlen($tokens[$s])));
}
$first_token = true;
$tmp = "";
// If all words we have extracted are equal, we add that
// word to the $output string. Otherwise we add '+%s%'.
for ($s = 0; $s < count($strings); $s++) {
// In the first iteration we just extract the word. We
// will start comparing from the next iteration.
if ($first_token) {
$tmp = $tokens[$s];
$first_token = false;
} else {
// If the words are not the same, we will add '+%s%' and
// exit the loop.
if ($tokens[$s] != $tmp) {
$tmp = "+%s%";
break;
}
}
}
// Add the word to the $output string. If it's the first
// word we don't add a white space before it.
if ($output == "") {
$output .= $tmp;
} else {
$output .= " $tmp";
}
}
return $output;
}
使用示例:
$strings = [
'This is +1% better than last time!',
'This is +2% better than last time!',
'This is +3% better than last time!',
'This is +4% better than last time!',
'This is +5% better than last time!',
];
echo myfunc($strings);
答案 1 :(得分:1)
如果您知道类似字符串的数组只会在一个地方有所不同,那么您可以从一开始就比较它们直到它们不同,从结尾直到它们不同并记录这些偏移。然后从第一个差异开始提取字符串,直到与数组中每个字符串的最后一个差异。
答案 2 :(得分:1)
非常感谢大家的帮助,所有这些都给了我很好的提示,告诉我们去哪里。这是解决这个问题的解决方案/类,这是Vicente Olivert Riera的答案和FlyingFoX在他/她的答案中解释的代码的扩展:
class StringDiff
{
/**
* The unformatted string to be used in the
* vsprintf call
* @var string
*/
protected $unformattedString = '';
/**
* Array with arguments replacing the %s in the
* unformatted string
* @var array
*/
protected $args = [];
/**
* Returns the arguments to be used for a vsprintf
* call along with the format string
* @return array
*/
public function getArgs()
{
return $this->args;
}
/**
* Returns the unformatted string to be used in
* a vsprint call along with the arguments
* @return string
*/
public function getUnformattedString()
{
return $this->unformattedString;
}
/**
* Takes an array argument of very similarly formatted
* strings and fills in the $unformattedString and $args
* variables from the data provided
* @param array $strings Group of very similar strings
* @return void
*/
public function run(array $strings)
{
// If there are no strings, return nothing
if (count($strings) == 0) return '';
// Replacing % with %% so the vsprintf call doesn't
// bug the arguments
$strings = str_replace('%', '%%', $strings);
$num_words = 0;
// Explodes each string into many smaller containing
// only words
foreach($strings as $key => $string)
{
$strings[$key] = explode(' ', $string);
}
$num_words = count($strings[0]);
// Array containing the indices of the substrings
// that are different
$sub_str_nr = [];
// Loops through all the words in each string
for ($n = 0; $n < $num_words; $n++)
{
// First round only sets the string to be compared with
$first_round = true;
for ($s = 0; $s < count($strings); $s++)
{
if ($first_round)
{
$first_round = false;
$tmp[0] = $strings[$s][$n];
}
else
{
$tmp[1] = $strings[$s][$n];
if ($tmp[0] == $tmp[1])
{
$tmp[0] = $tmp[1];
}
else
{
if (!in_array($n, $sub_str_nr))
{
$sub_str_nr[] = $n;
}
}
}
}
}
// Array to hold the arguments, i.e. all the strings
// that differ from each other. From these the differences
// will be deduced and put into the $this->args variable
$args = [];
foreach($sub_str_nr as $nr)
{
$tmpArgs = [];
for ($a = 0; $a < count($strings); $a++)
{
$tmpArgs[] = $strings[$a][$nr];
}
$args[] = $tmpArgs;
}
foreach($args as $key => $arg)
{
// Offset from the beginning of the string that is still the same
$front_offset = 0;
// If the offset from the beginning has been maxed
$front_flag = true;
// Offset from the end of the string that is still the same
$back_offset = 0;
// Id the offset from the end has been maxed
$back_flag = true;
// The string to be compared against is the first in line
$tmp = $arg[0];
while ($front_flag || $back_flag)
{
// Flag 1 & 2 limits to only one increase of offset per loop
$flag1 = true;
$flag2 = true;
for ($a = 1; $a < count($strings); $a++)
{
// The two following if statements compare substring
// to substring of length one
if ($front_flag && $flag1)
{
if (substr($tmp, $front_offset, 1) != substr($arg[$a], $front_offset, 1) || is_numeric(substr($arg[$a], $front_offset, 1)))
{
$front_flag = false;
}
else
{
$front_offset++;
$flag1 = false;
}
}
if ($back_flag && $flag2)
{
if (substr($tmp, strlen($tmp) - $back_offset - 1, 1) != substr($arg[$a], strlen($arg[$a]) - $back_offset - 1, 1) || is_numeric(substr($arg[$a], strlen($arg[$a]) - $back_offset - 1, 1)))
{
$back_flag = false;
}
else
{
$back_offset++;
$flag2 = false;
}
}
}
}
// Sets the $this->args variable with the found arguments
foreach($arg as $arkey => $ar)
{
$this->args[$arkey][$key] = (float)substr($arg[$arkey], $front_offset, strlen($arg[$arkey]) - $back_offset - $front_offset);
}
// Changes the strings for the unformatted string, switches
// out the varying part to %s
$strings[0][$sub_str_nr[$key]] = substr($arg[0], 0, $front_offset) . '%s' . substr($arg[0], strlen($arg[0]) - $back_offset, $back_offset);
}
// Creates the unformatted string from the array of
// words, which originates from the original long string
$unformattedString = '';
foreach($strings[0] as $string)
{
$unformattedString.= ' ' . $string;
}
// Trim whitespaces in the beginning and end of the
// formatted string
$this->unformattedString = trim($unformattedString);
return;
}
}
使用方法:
$stringd = new StringDiff;
$test_array = [
"Your Cooldown Reduction cap is increased to 41% and you gain 1% Cooldown Reduction",
"Your Cooldown Reduction cap is increased to 42% and you gain 2% Cooldown Reduction",
"Your Cooldown Reduction cap is increased to 43% and you gain 3% Cooldown Reduction",
"Your Cooldown Reduction cap is increased to 44% and you gain 4% Cooldown Reduction",
"Your Cooldown Reduction cap is increased to 45% and you gain 5% Cooldown Reduction",
];
$stringd->run($test_array);
foreach($stringd->getArgs() as $arg)
{
echo vsprintf($stringd->getUnformattedString(), $arg) . '<br>';
}
输出:
Your Cooldown Reduction cap is increased to 41% and you gain 1% Cooldown Reduction
Your Cooldown Reduction cap is increased to 42% and you gain 2% Cooldown Reduction
Your Cooldown Reduction cap is increased to 43% and you gain 3% Cooldown Reduction
Your Cooldown Reduction cap is increased to 44% and you gain 4% Cooldown Reduction
Your Cooldown Reduction cap is increased to 45% and you gain 5% Cooldown Reduction
array(5) {
[0]=>
array(2) {
[0]=>
float(41)
[1]=>
float(1)
}
[1]=>
array(2) {
[0]=>
float(42)
[1]=>
float(2)
}
[2]=>
array(2) {
[0]=>
float(43)
[1]=>
float(3)
}
[3]=>
array(2) {
[0]=>
float(44)
[1]=>
float(4)
}
[4]=>
array(2) {
[0]=>
float(45)
[1]=>
float(5)
}
}
Your Cooldown Reduction cap is increased to %s%% and you gain %s%% Cooldown Reduction
是的,如果你想知道,这与Riot API有关。
如果您有改进建议或任何更改,请随时在下方发表评论:)