难以置信,一个小小的需求让我捣鼓出一个提效的网站来

news2025/1/11 2:26:04

难以置信,一个小小的需求让我捣鼓出一个提效的网站来

需求介绍

事情是这样的,有个群友在业务当中碰到一个小小的需求,需求是这样的: 页面当中存在多个输入框,输入框的 value 值是一个数值组成的字符串(盲猜应该是身份证号码),这个字符串的位数是 15 位或者是 18 位,例如:'621848063680370'(15 位)和'621848063688370808'(18 位),然后默认的值是这样的,现在问题来了,需求希望在这些数值中插入空白符号,比如 15 位的数字就按照 6 + 6 + 3 的格式分隔,分隔的时候需要使用空白符号。比如'621848063680370'分隔后应该变成'621848 063680 370',也就是数字位数到了第 6 位就加个空白符号分隔,...依次类推,而 18 位数字的分割规则则是:6 + 4 + 4 + 4。比如'621848063688370808'应该分隔成'621848 0636 8837 0808'。

这个需求就是对字符串的处理,提到分隔替换,那么我们就可以想到强大的字符串替换方法 replace,这个方法可以接受 2 个参数,一个参数通常是一个正则表达式,第二个参数则是一个回调函数,用于定义替换后返回字符串。因此,我的第一个想法就是使用正则表达式去处理,如何处理呢?

原理分析

首先我们需要去理解这个规则,从需求我们可以发现,不同的位数,规则就会有所不同,因此我们可以提前用一个数据来表示这种规则,为了保持良好的扩展性,我设计了如下字段:

type spaceRule = {
  digit: number; // 位数
  rule: RegExp; //规则
  symbolNumber: number; // 插入符号数量
  symbolName: string; // 插入符号
};

可以看到,我设计了四个参数,正如注释所说,每一个参数都有具体的含义,为什么要如此设计参数呢?还是看需求,我们需求首先是限定了数字的位数,只可能是 15 位或者是 18 位,那如果存在 19 位又或者 20 位的场景呢?因此我们需要设计一个位数的参数,然后是每一个位数对应的规则是不一样的,因此我们也需要设计一个 rule 参数,然后是插入符号数量,也许会存在 1 个空白,2 个空白等等场景,或者我们不一定插入空白符号,也有可能是其它符号例如"-"等等,因此就设计 symbolNumber 和 symbolName 参数。

既然规则是类似 6 + 6 + 3 这样的规则,因此我们想到使用正则表达式来完成这个功能是可以的,我们将其拆分开来,分成 3 个分组,第一个分组匹配 6 个数字,第二个分组匹配 6 个数字,第三个分组匹配 3 个数字,然后针对分组之间插入特定的符号即可。

正则表达式中匹配数字可以使用'\d'来表示,然后匹配位数位 6,我们就可以使用量词'{6,}'来表示,因此我们的 6 + 6 + 3 规则就可以写成如下:

const rule = /(\d{6,})(\d{6,})(\d{3,})/g;

replace方法核心参数

接下来根据 mdn 对 replace 第二个参数回调函数参数的介绍,我们就知道,如果匹配到了正则表达式,则回调函数的参数会是如下所示:

function replacer(match, p1, p2, /* …, */ pN, offset, string, groups) {
  return replacement;
}

其中 p1,p2...pN 就是我们这里需要用到的匹配分组,有个专业的名词叫做捕获组,前面 9 个捕获组对应的就是正则表达式实例对象的$1....$9 属性。

然后其返回值就会用作字符串被替代的部分,因此这里我们可以使用展开运算符将中间的捕获组截取出来,然后利用 join 方法,传入需要插入的符号即可转成符合需求的字符串。

ps: 由于这里经过我对谷歌浏览器的测试,replacer 的倒数第 3 个参数不存在,因此我这里截取结束索引值就是 args.length - 2。

因此,我们可以写出如下代码:

const spaceRule = {
  digit: 15,
  rule: /(\d{6,})(\d{6,})(\d{3,})/g,
  symbolNumber: 1,
  symbol: " ",
};
const allInputs = document.querySelectorAll("input");
allInputs.forEach((item) => {
  const v = item.value;
  const { symbolNumber, symbol, rule } = spaceRule;
  item.value = v.replace(rule, (...args) =>
    args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber))
  );
});

这样就达到了将输入框中 15 位数字中间插入符号的需求,并且满足 6 + 6 + 3 的规则。如果是 18 位数字,规则也变成了 6 + 4 + 4 + 4,我们就只需要修改 digit 和 rule 值即可,如下:

const spaceRule = {
  digit: 18,
  rule: /(\d{6,})(\d{4,})(\d{4,})(\d{4,})/g,
  symbolNumber: 1,
  symbol: " ",
};
const allInputs = document.querySelectorAll("input");
allInputs.forEach((item) => {
  const v = item.value;
  const { symbolNumber, symbol, rule } = spaceRule;
  item.value = v.replace(rule, (...args) =>
    args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber))
  );
});

可以看到,我们核心的替换逻辑是没有变动的,变动的只是我们定义的规则而已,哪怕是用在 vue 和 react 框架当中,我们也只是修改一些框架特定的语法,但其实核心替换逻辑还是不会变动,比如 vue2 代码如下:

const spaceRule = {
  digit: 18,
  rule: "6 + 4 + 4 + 4",
  symbolNumber: 1,
  symbol: " ",
};
export default {
  methods: {
    onFormatValue(item) {
      const { symbolNumber, symbol, rule } = spaceRule;
      const regExp = new RegExp(
        `${rule
          .split("+")
          .map((item) => `(\\d{${Number(item)},})`)
          .reduce((res, item) => ((res += item), res), "")}`,
        "g"
      );
      const formatValue = item.replace(regExp, (...args) =>
        args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber))
      );
      return formatValue;
    },
  },
};

vue3 代码如下:

const spaceRule = {
  digit: 18,
  rule: "6 + 4 + 4 + 4",
  symbolNumber: 1,
  symbol: " ",
};
const onFormatValue = computed(() => (item) => {
  const { symbolNumber, symbol, rule } = spaceRule;
  const regExp = new RegExp(
    `${rule
      .split("+")
      .map((item) => `(\\d{${Number(item)},})`)
      .reduce((res, item) => ((res += item), res), "")}`,
    "g"
  );
  const formatValue = item.replace(regExp, (...args) =>
    args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber))
  );
  return formatValue;
});

react 代码如下:

const spaceRule = {
  digit: 18,
  rule: "6 + 4 + 4 + 4",
  symbolNumber: 1,
  symbol: " ",
};
const FormatInput = () => {
  const onFormatValue = React.useCallback((value) => {
    const { symbolNumber, symbol, rule } = spaceRule;
    const regExp = new RegExp(
      `${rule
        .split("+")
        .map((item) => `(\\d{${Number(item)},})`)
        .reduce((res, item) => ((res += item), res), "")}`,
      "g"
    );
    const formatValue = value.replace(regExp, (...args) =>
      args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber))
    );
    return formatValue;
  }, []);
  return <input type="text" value={onFormatValue("621848063688370808")} />;
};
export default FormatInput;

纵观以上的代码,我们可以发现核心的 js 逻辑是没有变动的,变动的只是一些框架有的概念而已,例如 vue2 中,我们使用方法结合双向绑定指令 v-model 来修改,而 react 也是同理,vue3 我们则是使用计算属性来表示。

网站介绍

基于以上的分析,接下来,就是我们这个提效网站实现的雏形,首先来看一下网站,如下图所示:

截图截的不全,更详细可以点这里查看。

通过以上的网站展示,我们已经初步构思好了整个网站的构架:

  1. 创建规则的表单部分。
  2. 预览效果部分。
  3. 代码展示部分。

其中代码展示部分又提供了不同框架和原生版本的展示以及复制,同样的还提供了在线示例的下载,其它就是一些额外展示功能组件,没什么可说的,比如底部链接展示,头部组件,还有就是需求介绍展示组件。

核心原理我们已经知道了,接下来无非就是写好页面架构,技术选型上我们使用的是 vue3 + vite + naive-ui 组件库。

重点代码分析

核心页面我们也不必要介绍,这里只重点提一下一些重要功能的实现点,首先是代码压缩包的下载,我们采用的是 file-saver 和 jszip 库,代码很简单,如下所示:

const zip = new JSZip();
zip.file(
  `${codeTypeValue.value}-demo.html`,
  htmlTemplate(
    renderTemplateCode.value.html,
    renderTemplateCode.value.js,
    codeTypeValue.value
  )
);
// 调用zip的generateAsync生成一个blob文件
const content = await zip.generateAsync({ type: "blob" });
// saveAs 方法实现下载
saveAs(content, `${codeTypeValue.value}-demo.zip`);

其实这里的 htmlTemplate 就是构造一个下载代码模板,如下所示:

import { CodeTemplateKey } from "./code";

export const getScriptTemplate = (type: CodeTemplateKey) => {
  if (type.includes("vue")) {
    const src =
      type === "vue2"
        ? "https://cdn.bootcdn.net/ajax/libs/vue/2.6.7/vue.min.js"
        : "https://cdn.bootcdn.net/ajax/libs/vue/3.3.4/vue.global.min.js";
    return `<script src="${src}"></script>`;
  } else if (type === "react") {
    return `<script src="https://cdn.bootcdn.net/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/babel-standalone/7.22.17/babel.min.js"></script>`;
  } else {
    return "";
  }
};
export const htmlTemplate = (
  htmlContent: string,
  jsContent: string,
  type: CodeTemplateKey
) => `
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>输入框生成插入符号 ${type} demo</title>
    <style>
        body {
            margin: 0;
        }

        input {
            padding: 8px 24px;
            border: 0;
            border-radius: 15px;
            background-color: #fefefe;
            color: rgba(0, 0, 0, .85);
            margin: 8px 0;
            border: 1px solid #232323;
            min-width: 250px;
        }
    </style>
</head>
<body>
    <div id="app">${htmlContent}</div>
    ${getScriptTemplate(type)}
    <script type="${
      type === "react" ? "text/babel" : "text/javascript"
    }">${jsContent}</script>
</body>
</html>`;

代码模板如下:

export const codeTemplate = {
  js: (options: IFormValue) => ({
    html: Array.from({ length: options.inputNumber })
      .map((_, i) => options.inputContent[i])
      .map((item) => `<input type="text" value="${item}"/>\n`)
      .join(""),
    js: `
const spaceRule = {
    digit: ${options.digit},
    rule: /${options.rule
      .split("+")
      .map((item) => `(\\d{${Number(item)},})`)
      .reduce((res, item) => ((res += item), res), "")}/g,
    symbolNumber: ${options.symbolNumber},
    symbol: '${options.symbol}'
};
const allInputs = document.querySelectorAll('input');
allInputs.forEach(item => {
    const v = item.value;
    const { symbolNumber, symbol, rule } = spaceRule;
    item.value = v.replace(rule, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));
})`,
  }),
  vue2: (options: IFormValue) => ({
    html: Array.from({ length: options.inputNumber })
      .map((_, i) => options.inputContent[i])
      .map((_) => `<input type="text" v-model="onFormatValue('${_}')" />\n`)
      .join(""),
    js: `
const spaceRule = {
    digit: ${options.digit},
    rule: '${options.rule}',
    symbolNumber: ${options.symbolNumber},
    symbol: '${options.symbol}'
};
export default {
    methods:{
        onFormatValue(item){
            const { symbolNumber,symbol,rule } = spaceRule;
            const regExp = new RegExp(\`\${rule.split('+').map(item => \`(\\\\d{\$\{Number(item)\},})\`).reduce((res, item) => (res += item, res), '')}\`, 'g');
            const formatValue = item.replace(regExp, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));
            return formatValue;
        }
    }
}
      `,
  }),
  vue3: (options: IFormValue) => ({
    html: Array.from({ length: options.inputNumber })
      .map((_, i) => options.inputContent[i])
      .map((_) => `<input type="text" :value="onFormatValue('${_}')" />\n`)
      .join(""),
    js: `
const spaceRule = {
    digit: ${options.digit},
    rule: '${options.rule}',
    symbolNumber: ${options.symbolNumber},
    symbol: '${options.symbol}'
};
const onFormatValue = computed(() => (item) => {
    const { symbolNumber,symbol,rule } = spaceRule;
    const regExp = new RegExp(\`\${rule.split('+').map(item => \`(\\\\d{\$\{Number(item)\},})\`).reduce((res, item) => (res += item, res), '')}\`, 'g');
    const formatValue = item.replace(regExp, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));
    return formatValue;
})
      `,
  }),
  react: (options: IFormValue) => ({
    html: "",
    js: `
const spaceRule = {
    digit: ${options.digit},
    rule: '${options.rule}',
    symbolNumber: ${options.symbolNumber},
    symbol: '${options.symbol}'
};
const FormatInput = () => {
    const onFormatValue = React.useCallback((value) => {
        const { symbolNumber,symbol,rule } = spaceRule;
        const regExp = new RegExp(\`\${rule.split('+').map(item => \`(\\\\d{\$\{Number(item)\},})\`).reduce((res, item) => (res += item, res), '')}\`, 'g');
        const formatValue = value.replace(regExp, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));
        return formatValue;
    },[])
    return (
        ${Array.from({ length: options.inputNumber })
          .map((_, i) => options.inputContent[i])
          .map((_) => `<input type="text" value={onFormatValue('${_}')} />`)
          .join("")}
    )
}
export default FormatInput;
        `,
  }),
};

export const demoCodeTemplate = {
  js: (options: IFormValue) => ({
    html: Array.from({ length: options.inputNumber })
      .map((_, i) => options.inputContent[i])
      .map((item) => `<input type="text" value="${item}"/>\n`)
      .join(""),
    js: `
const spaceRule = {
    digit: ${options.digit},
    rule: /${options.rule
      .split("+")
      .map((item) => `(\\d{${Number(item)},})`)
      .reduce((res, item) => ((res += item), res), "")}/g,
    symbolNumber: ${options.symbolNumber},
    symbol: '${options.symbol}'
};
const allInputs = document.querySelectorAll('input');
allInputs.forEach(item => {
    const v = item.value;
    const { symbolNumber, symbol, rule } = spaceRule;
    item.value = v.replace(rule, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));
})`,
  }),
  vue2: (options: IFormValue) => ({
    html: Array.from({ length: options.inputNumber })
      .map((_, i) => options.inputContent[i])
      .map((_) => `<input type="text" v-model="onFormatValue('${_}')" />\n`)
      .join(""),
    js: `
const spaceRule = {
    digit: ${options.digit},
    rule: '${options.rule}',
    symbolNumber: ${options.symbolNumber},
    symbol: '${options.symbol}'
};
new Vue({
    el:"#app",
    methods:{
        onFormatValue(item){
            const { symbolNumber,symbol,rule } = spaceRule;
            const regExp = new RegExp(\`\${rule.split('+').map(item => \`(\\\\d{\$\{Number(item)\},})\`).reduce((res, item) => (res += item, res), '')}\`, 'g');
            const formatValue = item.replace(regExp, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));
            return formatValue;
        }
    }
});
      `,
  }),
  vue3: (options: IFormValue) => ({
    html: Array.from({ length: options.inputNumber })
      .map((_, i) => options.inputContent[i])
      .map((_) => `<input type="text" :value="onFormatValue('${_}')" />\n`)
      .join(""),
    js: `
const spaceRule = {
    digit: ${options.digit},
    rule: '${options.rule}',
    symbolNumber: ${options.symbolNumber},
    symbol: '${options.symbol}'
};
Vue.createApp({
    setup() {
      const onFormatValue = Vue.computed(() => (item) => {
        const { symbolNumber,symbol,rule } = spaceRule;
        const regExp = new RegExp(\`\${rule.split('+').map(item => \`(\\\\d{\$\{Number(item)\},})\`).reduce((res, item) => (res += item, res), '')}\`, 'g');
        const formatValue = item.replace(regExp, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));
        return formatValue;
      })
      return {
        onFormatValue
      }
    }
  }).mount('#app')
      `,
  }),
  react: (options: IFormValue) => ({
    html: "",
    js: `
const spaceRule = {
    digit: ${options.digit},
    rule: '${options.rule}',
    symbolNumber: ${options.symbolNumber},
    symbol: '${options.symbol}'
};
const FormatInput = () => {
    const onFormatValue = React.useCallback((value) => {
        const { symbolNumber,symbol,rule } = spaceRule;
        const regExp = new RegExp(\`\${rule.split('+').map(item => \`(\\\\d{\$\{Number(item)\},})\`).reduce((res, item) => (res += item, res), '')}\`, 'g');
        const formatValue = value.replace(regExp, (...args) => args?.slice(1, args.length - 2)?.join(symbol.repeat(symbolNumber)));
        return formatValue;
    },[])
    return (
        ${Array.from({ length: options.inputNumber })
          .map((_, i) => options.inputContent[i])
          .map((_) => `<input type="text" value={onFormatValue('${_}')} />`)
          .join("")}
    )
}
const root = ReactDOM.createRoot(document.querySelector('#app'));
root.render(<FormatInput />);
        `,
  }),
};

export type CodeTemplateKey = keyof typeof codeTemplate;

// 代码key列表
export const codeTypeList = Object.keys(codeTemplate) as CodeTemplateKey[];

// 代码版本下拉列表
export const selectCodeTypeList = codeTypeList.map((item) => ({
  label: item,
  value: item,
}));

然后就是我们的 copy 复制代码功能函数的实现,原理就是利用了 navigator.clipboard api,如果浏览器不支持,我们就使用 document.execCommand api,工具函数代码如下所示:

export const copyHandler = (str: string, dialog?: DialogApi) => {
  const confirm = (title = "温馨提示", content = "已复制到剪切板") => {
    dialog?.success({
      title: title,
      content: content,
      positiveText: "确定",
    });
  };
  const baseCopy = (copyText: string) =>
    new Promise<void>((resolve, reject) => {
      // 判断是否存在clipboard并且是安全的协议
      if (navigator.clipboard && window.isSecureContext) {
        navigator.clipboard
          .writeText(copyText)
          .then(() => {
            resolve();
          })
          .catch(() => {
            reject(new Error("复制失败"));
          });
      } else {
        // 否则使用被废弃的execCommand
        const input = document.createElement("input") as HTMLInputElement;
        input.value = copyText;
        // 使input不在viewport,同时设置不可见
        input.style.position = "absolute";
        input.style.left = "-9999px";
        input.style.top = "-9999px";
        document.body.append(input);
        input.focus();
        input.select();
        // 执行复制命令并移除文本框
        if (document.execCommand) {
          document.execCommand("copy");
          resolve();
        } else {
          reject(new Error("复制失败"));
        }
        input.remove();
      }
    });
  baseCopy(str)
    .then(() => confirm())
    .catch(() => confirm("温馨提示", "复制失败"));
};

遇到的有意思的问题分析

除此之外,其它都是一些很好理解的基础代码,因此不需要讲解,这里讲一个让我觉得有意思的问题,也是在源码当中有备注,那就是被代理的对象会被污染,可以看到我们的 config.ts 里面写了 2 个最基础的表单配置对象:

export const defaultFormValue = {
  digit: 15,
  rule: "6 + 6 + 3",
  symbol: " ",
  symbolNumber: 1,
  inputNumber: 1,
  inputContent: ["621848063680370"],
};
export const baseDefaultFormValue = {
  digit: 15,
  rule: "6 + 6 + 3",
  symbol: " ",
  symbolNumber: 1,
  inputNumber: 1,
  inputContent: ["621848063680370"],
};

用来设置表单的初始值对象,我在监听用户修改输入框值之后去改变绑定的初始值,发现绑定的初始值被修改污染了,哪怕我采用了复制对象副本(使用 JSON 和展开运算符来复制),都会修改原始配置对象。我们的表单配置对象是这样的:

const formValue = ref({ ...defaultFormValue });

也就是说我对 formValue 的修改会影响到 defaultFormValue,这就让我感觉很奇怪,所以我想创建一个 baseDefaultFormValue 的方式去解决这个问题,这样我在重置表单数据的时候,就能够重置为最初始的数据,如下:

const handleResetClick = () => {
  formRef.value?.restoreValidation();
  // 不重新写一个defaultFormValue已经被污染了
  formValue.value = {
    ...baseDefaultFormValue,
  };
  emit("on-submit", formValue.value);
};

这个问题,目前我还没有分析出原因来,如果有感兴趣的大佬,可以通过参考源码调试看看问题,我就没有时间去研究这个问题呢。

这些点是我觉得值得分析的地方,其它就没啥了,感谢阅读到这里,如果觉得有帮助可以点赞收藏,顺带可以帮我的项目点个 star,感激不尽。

另外给大家整理一部分大厂的面经和一些真题加上一些项目

转发本文+关注+私信【学习】或添加下方下助理即可领取更多资料!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1282273.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何将Java条码Dynamsoft Barcode Reader集成到命令行、GUI和Web应用程序中

Dynamsoft Barcode Reader SDK一款多功能的条码读取控件&#xff0c;只需要几行代码就可以将条码读取功能嵌入到Web或桌面应用程序。这可以节省数月的开发时间和成本。能支持多种图像文件格式以及从摄像机或扫描仪获取的DIB格式。使用Dynamsoft Barcode Reader SDK&#xff0c;…

C++: 多态基本概念及原理

多态的基本概念&#xff1a; 多态是 C 面向对象三大特性之一 多态分为两类&#xff1a; 静态多态 : 函数重载 和 运算符重载属于静态多态&#xff0c;复用函数名 动态多态 : 派生类和虚函数实现运行时多态 静态多态和动态多态区别&#xff1a; 静态多态的函数地址早绑定 …

手机充电器市场分析:预计2028年将达到82亿美元

在5G时代飞速发展的今天&#xff0c;随着科技的进步、应用的发展以及人们对以智能手机、平板电脑、智能穿戴设备为代表的智能终端设备追求越来越高的品质和功能&#xff0c;智能终端设备产品的更新换代的速度越来越快&#xff0c;这也将给全球智能终端充储电产品市场带来更大的…

linux resin的安装

1. 下载安装包 1.1 下载地址&#xff1a;https://caucho.com/products/resin/download 这里我下载的是普通版本的resin&#xff0c;没有选resin pro 版本。 科普一下&#xff0c;从性能上来说 resin和resin pro 版本的性能没区别。 resin pro 版本的 和resin 普通版本的文件是…

Prometheus+Grafana搭建日志采集

介绍 一、什么是日志数据采集 日志数据采集是指通过各种手段获取应用程序运行时产生的各类日志信息&#xff0c;并将这些信息存储到特定的地方&#xff0c;以便后续分析和使用。通常情况下&#xff0c;这些日志信息包括系统运行状态、错误信息、用户操作记录等等。通过对这些…

外贸建站是WP还是CMS?海洋建站教程指南?

外贸建站选WP还是CMS系统&#xff1f;外贸企业网站建站怎么做&#xff1f; 随着全球化的不断发展&#xff0c;越来越多的企业开始拓展海外市场&#xff0c;外贸建站成为了这些企业的必备项目。然而&#xff0c;选择使用哪种建站系统却是一个让人头疼的问题。那么&#xff0c;海…

Pytorch深度强化学习1-5:详解蒙特卡洛强化学习原理

目录 0 专栏介绍1 蒙特卡洛强化学习2 策略评估原理3 策略改进原理3.1 同轨蒙特卡洛强化学习3.2 离轨蒙特卡洛强化学习 0 专栏介绍 本专栏重点介绍强化学习技术的数学原理&#xff0c;并且采用Pytorch框架对常见的强化学习算法、案例进行实现&#xff0c;帮助读者理解并快速上手…

centos安装Python3之后yum不能使用异常

场景&#xff1a; 需要在centos上安装Python3&#xff0c;但是安装Python3之后出现yum不能使用的问题。 问题描述 在centos上安装python3之后出现yum使用不了问题&#xff0c;使用yum会报如下信息&#xff1a; [roothadoop101~]# yum install wgetFile "/usr/bin/yum&q…

Synchronized关键字的底层原理

Synchronized实现 Synchronized创建的时候一个互斥的对象锁&#xff0c;每次只有一个线程可以获取该锁。 其底层主要是基于Monitor实现的&#xff0c;在对象的对象头中存储了MarkWord存储的就是Monitor的地址。 对象的内存结构 对象在内存中存储主要分为三个部分&#xff1a…

【IEEE独立出版|EI会议征稿】2024年第四届消费电子与计算机工程国际学术会议(ICCECE 2024)

2024年第四届消费电子与计算机工程国际学术会议&#xff08;ICCECE 2024&#xff09; 2024 4th International Conference on Consumer Electronics and Computer Engineering 进入21世纪以来&#xff0c;计算机技术的高速发展带来了消费电子产品的快速更迭。在技术迅速发展历…

docker配置redis主从、哨兵集群

docker配置redis主从、哨兵集群 搭建redis主从 准备工作 在/usr/local/software/redis/文件夹下建立如下的文件夹、文件 rootlocalhost redis]# mkdir -p 6379/conf 6379/data 6379/log [rootlocalhost redis]# mkdir -p 6380/conf 6380/data 6380/log [rootlocalhost re…

基于ssm的疫苗预约系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于ssm的疫苗预约系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring Spri…

【Python动漫系列】喜羊羊(完整代码)

文章目录 喜羊羊环境需求完整代码程序分析系列文章喜羊羊 喜羊羊是中国大陆一部儿童动画片《喜羊羊与灰太狼》中的主角之一。这部动画片自2005年开始播出,成为许多中国儿童最喜欢的动画之一。 喜羊羊是一只体型较小、毛色洁白的绵羊,性格机灵活泼,聪明机智。他是一只勇敢而…

python获取阿里云云解析dns的域名解析记录

最近由于工作原因接触到阿里云的服务&#xff0c;我需要实时获取所有的域名信息&#xff0c;用于对其进行扫描&#xff0c;因此写了一个自动化爬取脚本 给需要的人分享。 &#xff08;阿里云有官方的demo&#xff0c;有兴趣的可以自己看一下&#xff0c;后面也会放链接&#xf…

Cesium 顶点吸附和区域拾取

Cesium 顶点吸附和区域拾取 基于深度实现可以自定义拾取范围大小 // 顶点吸附// const result pickAreaHelper.pickNearest(viewer.scene, movement.endPosition, 32, 32);// 区域拾取const result pickAreaHelper.pickArea(viewer.scene, movement.endPosition, 32, 32);顶…

深度学习——第3章 Python程序设计语言(3.2 Python程序流程控制)

3.2 Python程序流程控制 目录 1.布尔数据类型及相关运算 2.顺序结构 3.选择&#xff08;分支&#xff09;结构 4.循环结构 无论是在机器学习还是深度学习中&#xff0c;Python已经成为主导性的编程语言。而且&#xff0c;现在许多主流的深度学习框架&#xff0c;例如PyTorc…

揭秘强化学习:Python 实践指南

一、说明 强化学习 (RL) 是机器学习和人工智能 (AI) 的一个子领域&#xff0c;专注于开发能够通过与环境交互进行学习的智能代理。与传统的监督和无监督学习不同&#xff0c;强化学习主要关注动态、顺序环境中的决策。它在人工智能中具有重要意义&#xff0c;特别是在自主代理必…

MySQL 忘记root密码后重置密码操作

在忘记 MySQL 密码的情况下&#xff0c;可以通过 --skip-grant-tables 关闭服务器的认证&#xff0c;然后重置 root 的密码&#xff0c;具体操作步骤如下。 步骤 1)&#xff1a;关闭正在运行的 MySQL 服务。打开 cmd 进入 MySQL 的 bin 目录。 步骤 2)&#xff1a;输入mysqld -…

【面试经典150 | 二分查找】搜索二维矩阵

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;二分查找 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等…

他山之石,可以攻玉|银行业数据中心数字化转型之模型篇 04(完结)

导语&#xff1a;他山之石&#xff0c;可以攻玉&#xff5c;银行业数据中心数字化转型之模型篇 04&#xff08;完结&#xff09; 银行业数据中心数字化转型是一项系统性工程既涉及管理层面转型——包括数字化转型战略、基础架构和技术架构转型、技术创新和知识体系转型&#xf…