【问题标题】:How to convert given text to array with given key in Javascript如何在Javascript中使用给定键将给定文本转换为数组
【发布时间】:2021-10-27 18:08:36
【问题描述】:

我正在创建一个简单的 OCR 应用程序,它从卡片中读取信息并成功地将图像转换为文本。这里是转换文本的示例

名称:绿巨人色+绿型英雄

名称:毒液颜色:黑色型反英雄

我们可以看到有时冒号转换为 + 或其他符号,关键是如何将该字符串转换为具有预定义键(在我们的例子中是名称、颜色和类型)的对象,最好的方法是什么?

【问题讨论】:

  • 展示您的最佳尝试,并解释它是如何失败的,以及您的期望。 SO 不是免费的代码编写服务。
  • 这里的变量太多了,但基本上你可以用“颜色”分割,你的数组中有2个元素,拳头是你可以删除名称和任何非字母数字字符的名称,你将第一个元素作为名称,第二个元素将是您的颜色,您还必须去除所有非字母数字字符。
  • @Gabriel 你能给我看一个例子,这样我就可以得到一个小提示我接下来应该做什么

标签: javascript


【解决方案1】:

类似这样,我假设您的输出有多行,并且名称或颜色不包含非字母数字字符,如果包含,您将不得不将它们从正则表达式中排除。

let myArray = [];
let string = `Name :Hulk Color + Green Type Hero
Name :Venom Color :Black Type Anti Hero`;
// split by newline so we get the lines
let lines = string.split("\n");
// console.log(lines);
lines.forEach(transform);

function transform(line) {
  let obj = {};
  let parts = line.split(/Color|Type/);
  obj['name'] = parts[0].replace(/[^0-9a-z ]/gi, "").replace("Name", "").replace(/\s\s+/g, ' ').trim();
  obj['color'] = parts[1].replace(/[^0-9a-z ]/gi, "").replace(/\s\s+/g, ' ').trim();
  obj['type'] = parts[2].replace(/[^0-9a-z ]/gi, "").replace(/\s\s+/g, ' ').trim();
  myArray.push(obj);
  // return obj;
}
// console.log(myArray);

// =============================== use array to split
let splitBy = ['name', 'color', 'type'];
let hero = 'Name :Hulk Color + Green Type Hero';

function heroToObj(hero, splitBy) {
  let obj = {};
  const regex = new RegExp(splitBy.join('|'), 'i');
  var parts = hero.split(regex);
  splitBy.forEach((key,index)=>obj[key] = parts[index+1].replace(/[^0-9a-z ]/gi, "").replace(/\s\s+/g, ' ').trim() )
  return obj;
}
const heroObject = heroToObj(hero, splitBy);
console.log(heroObject);

=========================== 另一个例子==================

let hero = 'Name :Hulk\nColor + Green\nType Hero\nAnother text \nanother some texts';
let myArray = [];
// split by newline so we get the lines
let lines = hero.split("\n");
let obj = {};
let splitBy = ['name', 'color', 'type'];
lines.forEach(heroToObj);
function heroToObj(line) {
  splitBy.forEach((prop) => {
    var regEx = new RegExp(prop, "ig");
    // clean the line to account for  '+Name :Hulk\n Color + Green\n-Type Hero\nAnother text \another some texts'
    line = line.replace(/[^0-9a-z ]/gi, "").trim();
    if (line.toLowerCase().startsWith(prop.toLowerCase())) obj[prop] = line.replace(/[^0-9a-z ]/gi, "").replace(/\s\s+/g, ' ').replace(regEx, '').trim()
  })
}

console.log(obj);

【讨论】:

  • 如果你只有一行,你可以将它直接传递给转换函数:transform("Name :Hulk Color + Green Type Hero");,你可以在函数内部return obj;而不是添加到数组myArray.push(obj)
  • 你错过了应该是英雄或反英雄的“类型”列
  • 在我看来,我们可以预定义一个给定键的数组,我们想要类似 ['name','color','type'] 的东西,然后使用该数组来拆分字符串
  • 已更新类型,因为这是 OCR 扫描,可能会添加许多伪影,最好有办法清洁每个部分,及时发现潜在问题并修复它们
  • 你可以看到我的更新答案,我添加了一个函数,它接受一行和一个数组并返回一个对象,数组元素用于拆分和对象键
【解决方案2】:

这是一个使用 named capturing groups 并使用类别/属性名称 ['Name', 'Color', Type'] 作为字符串中的分隔符的快速示例,将这些单词之间的所有字符捕获到适当命名的组中 [(?<name>.*), (?<color>.*), (?<type>.*)],并设置 i 标志以进行不区分大小写的匹配。

const regex = /Name(?<name>.*)Color(?<color>.*)Type(?<type>.*)/i,

当在这个正则表达式上调用exec() 时,命名匹配将在返回的匹配数组的groups 属性中可用。

从那里您只需要访问每个命名组并清理其关联的字符串,这里使用正则表达式替换开头的non-word(匹配[^A-Za-z0-9_])字符的\W或字符串的结尾。

const clean = (s) => s.replace(/^\W+|\W+$/, '');

最后,将它们组合成一个对象,这里使用for...of 循环迭代groups 对象的Object.keys(),清理每个匹配的字符串并将其分配给结果对象。

const parse_ocr_string = (str) => {

  const clean = (s) => s.replace(/^\W+|\W+$/g, '');

  const regex = /Name(?<name>.*)Color(?<color>.*)Type(?<type>.*)/i;
  const { groups } = regex.exec(str);

  const result = {};
  for (const k of Object.keys(groups)) {
    result[k] = clean(groups[k]);
  }

  return result;
};

const s1 = 'Name :Hulk Color + Green Type Hero';
const s2 = 'Name :Venom Color :Black Type Anti Hero';

const obj1 = parse_ocr_string(s1);
const obj2 = parse_ocr_string(s2);

console.log(obj1);
console.log(obj2);

但您也可以通过接受delimiters 参数并传递['String', 'key'] 对来通过new RegExp() 构造函数声明正则表达式来概括这一点。您仍然需要针对其他工件/区分大小写的问题进行调整,但这可能会让您了解如何进行。

const parse_ocr_string = (str, delimiters) => {

  const clean = (s) => s.replace(/^\W+|\W+$/g, '');

  const match_string = delimiters
    .map(([seq, key]) => `${seq}(?<${key}>.*)`)
    .join('');

  const regex = new RegExp(match_string, 'i');
  const { groups } = regex.exec(str);

  const result = {};
  for (const k of Object.keys(groups)) {
    result[k] = clean(groups[k]);
  }

  return result;
};

const s1 = 'Name :Hulk Color + Green Type =Hero';
// specify delimiters in some form, here tuples of ['Word', 'property']
const delimiters1 = [['Name', 'name'], ['Color', 'color'], ['Type', 'type']];

const obj1 = parse_ocr_string(s1, delimiters1);
console.log(obj1);

const s2 = 'AttaCk power: 24 Defense+ 90';
const delimiters2 = [['Attack Power', 'attack'], ['Defense', 'defense']];

const obj2 = parse_ocr_string(s2, delimiters2);
console.log(obj2);

【讨论】:

    猜你喜欢
    • 2021-04-18
    • 1970-01-01
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 2020-02-25
    • 1970-01-01
    • 2011-07-11
    • 2018-10-31
    相关资源
    最近更新 更多