【问题标题】:Replace random characters in string替换字符串中的随机字符
【发布时间】:2021-09-27 00:00:27
【问题描述】:

我正在尝试用一定数量的 一个特定的字符(即:"*"),我将在下面的代码中解释更多。

/**
 * Returns a string with replaced amount of strings with a set string
 * @param {string} str The input
 * @param {number} amountToReplace The amount of letters you want to replace
 * @param {string} generalReplace The general letter to replace with
 * @returns {string} Returns a string with the string thats finished
 */

var str = 'thisisastring';
var amountToReplace = 5; 
var generalReplace = '*'

// Function over here, e.g. with the name replacer
var returnMe = replacer(str, amountToReplac

对不起,如果参数听起来令人困惑,我对他们还是新手!

所以字符串,str 是输入字符串,amountToReplace 是您要替换的字母数量,generalReplace 是您要替换的通用字符。

如果金额是5,我期望的输出是这样的:

原文: thisisastring
输出: th*s**as*ri*g

返回的字符串应该替换字符串中的随机部分(但仍然做输入的数量,而不是做 5 个替换,而是返回 3 个作为常见匹配项)。

谢谢!

【问题讨论】:

  • 您要随机替换吗?
  • 是的,还有我想替换的一组字符串

标签: javascript string replace


【解决方案1】:

最小的(可以说是最简单的):

  • 将字符串拆分为数组[...str] // (is now an Array)
  • 循环在随机点插入一个带有替换字符的数组,例如:["t", "h", "i", ["*"], "i", ["*"], ...
  • continue 循环直到 iamount)不是 0 并且直到迭代索引处的当前值是一个数组。
  • 一旦完成,既然我们有一个二维数组,使用Array.prototype.flat() 使其成为一维数组,例如:["t", "h", "i", "*", "i", "*", ...
  • 并使用Array.prototype.join() 将其转换回字符串

const replacer = (str, i, rep) => {
  if (!str) return;                      // Do nothing if no string passed
  const arr = [...str];                  // Convert String to Array
  const len = arr.length
  i = Math.min(Math.abs(i), len);        // Fix to Positive and not > len 
  while (i) {
    const r = ~~(Math.random() * len);
    if (Array.isArray(arr[r])) continue; // Skip if is array (not a character)
    arr[r] = [rep];                      // Insert an Array with the rep char
    --i;
  }
  return arr.flat().join("");
};


console.log(replacer("thisisastring", 5, "*"));

上面的例子是久经考验的,即使在以下情况下也能很好地工作:

  • 没有字符串或为空
  • 字符串已经包含所有星号"*****"
  • amount 大于字符串长度
  • amount 是一个负整数

最长的:

  • 生成一个由 N (amountToReplace) 个随机唯一整数组成的数组
  • 将输入字符串转换为数组,迭代它,将随机索引中的每个字符替换为generalReplace“*”字符

/**
 * Create an array of unique integers
 * @param {Integer} len Array length
 * @param {Integer} max Max integer value
 * @returns {Array} Array of random Unique integers
 */
function genArrRandInt(len, max) {
  const nums = new Set();
  while (nums.size !== len) nums.add(Math.floor(Math.random() * max));
  return [...nums];
};

/**
 * Returns a string with replaced amount of strings with a set string
 * @param {string} str The input
 * @param {number} amountToReplace The amount of letters you want to replace
 * @param {string} generalReplace The general letter to replace with
 * @returns {string} Returns a string with the string thats finished
 */
function replacer(str, amountToReplace, generalReplace) {
  const strArr = [...str];
  const uniqueArr = genArrRandInt(amountToReplace, str.length);
  uniqueArr.forEach(i => strArr[i] = generalReplace);
  return strArr.join("");
}


const str = "thisisastring";
const amountToReplace = 5;
const generalReplace = "*";

// Function over here, e.g. with the name replacer
const returnMe = replacer(str, amountToReplace, generalReplace);
console.log(returnMe);

【讨论】:

  • 非常感谢您提供如此详细的信息,params 非常有用且具有描述性,令人惊叹的深入回答!
  • @Jeffplays2005 不客气
  • @Jeffplays2005 您可以在genArrRandInt(len, max) 中进行另一个修复,那就是使用max = Math.min(len, max); 来防止最大值大于字符串长度 - 如果您使用类似:replacer("aaa", 5, "*") since " aaa" 的长度小于 5。或者您可以在 replacer 函数中执行相同的操作。
  • 我只想提一下,第一个示例有一个非常小的小错误,而不是return res.flat().join("");,而是return arr.flat().join("");,因为 res 未定义!
  • @Jeffplays2005 非常感谢您的额外关注。认为arr 会比res 更好,但忘了重命名最新的:D 谢谢
【解决方案2】:

代码可能类似于:

function rand(min, max){
  let mn = min, mx = max;
  if(mx === undefined){
    mx = mn; mn = 0;
  }
  return mn+Math.floor(Math.random()*(mx-mn+1));
}
function randCharReplace(string, replaceWith = '*', replaceCount = 1){
  const a = string.split(''), m = a.length-1;
  const f = ()=>{
    return rand(0, m);
  }
  for(let i=0,r; i<replaceCount; i++){
    while(r === undefined || a[r] === replaceWith){
      r = f();
    }
    a[r] = replaceWith;
  }
  return a.join('');
}
console.log(randCharReplace('thisisastring',  '*', 5));

【讨论】:

    【解决方案3】:

    使用Set 的一种更有效的方法

    function replacer(str, len = 0, generalReplacer) {
      const length = len > str.length ? str.length : len,
               set = new Set(),
               newStr = [];
      
      while (set.size !== length) {
        set.add(Math.floor(Math.random() * str.length));
      }
    
      for (let i = 0; i < str.length; ++i) {
        set.has(i) ? newStr.push(generalReplacer) : newStr.push(str[i]);
      }
    
      return newStr.join("");
    }
    
    console.log(replacer("thisisastring", 5, "*"));
    console.log(replacer("thisisastring", 1, "*"));
    console.log(replacer("thisisastring", 7, "*"));

    【讨论】:

    • newStr.push("*") 应该是newStr.push(generalReplacer)
    【解决方案4】:

    function replacer(string, amount) {
        // If string contains all '*' return string
        if ([...string.matchAll(/\*/g)].length === string.length) {
            return string
        }
        // copy the ori string convert to array
        let res = [...string]
        let i = amount
        let e = ['*', ' ']
        // iterate amount times
        while (i >= 1) {
            // get random index in array
            const randomIdx = Math.floor(Math.random() * string.length)
            // get char at index
            const randomChar = res[randomIdx]
            // check if it not '*' or ' '
            if (!e.includes(randomChar)) {
                // replace char with '*'
                res.splice(randomIdx, 1, '*')
                i--
            }
        }
        return res.join('')
    }

    你可以试试这个。

    【讨论】:

    • replacer("asdf", 3) 返回错误结果,例如 asd*a*s*,而不是 *s**,如果字符串为 replacer("***", 3),我们将进入无限循环。
    • @RokoC.Buljan 感谢您指出错误。我编辑了我的答案。
    猜你喜欢
    • 2017-05-20
    • 1970-01-01
    • 1970-01-01
    • 2017-10-22
    • 2021-06-12
    • 2017-03-08
    • 1970-01-01
    • 2017-08-06
    • 2018-05-21
    相关资源
    最近更新 更多