我正在创建一个简单的OCR应用程序,它可以从卡中读取信息,并成功地将图像转换为文本。这里是转换文本的示例
名称:绿巨人颜色+绿色英雄
名称:毒液颜色:黑色反英雄
我们可以看到,有时冒号会转换为+或其他符号,关键是如何将该字符串转换为具有预定义键的对象(在我们的例子中是名称、颜色和类型),最好的方法是什么?
类似于此,我假设您的输出有多行,并且名称或颜色不包括非字母数字字符,如果包含非字母数字,则必须将它们从正则表达式中排除。
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(/ss+/g, ' ').trim();
obj['color'] = parts[1].replace(/[^0-9a-z ]/gi, "").replace(/ss+/g, ' ').trim();
obj['type'] = parts[2].replace(/[^0-9a-z ]/gi, "").replace(/ss+/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(/ss+/g, ' ').trim() )
return obj;
}
const heroObject = heroToObj(hero, splitBy);
console.log(heroObject);
==========================另一个例子================
let hero = 'Name :HulknColor + GreennType HeronAnother 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 :Hulkn Color + Greenn-Type HeronAnother 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(/ss+/g, ' ').replace(regEx, '').trim()
})
}
console.log(obj);
这里有一个使用命名捕获组的快速示例,并在字符串中使用类别/属性名称['Name'、'Color'、Type']作为delimeter,将这些单词之间的所有字符捕获到适当命名的组[(?<name>.*)
、(?<color>.*)
、(?<type>.*)
]中,并设置i
标志进行不区分大小写的匹配。
const regex = /Name(?<name>.*)Color(?<color>.*)Type(?<type>.*)/i,
在此正则表达式上调用exec()
时,命名的匹配将在返回的匹配数组的groups
属性中可用。
从那里,您只需要访问每个命名组并清除其关联的字符串,在这里使用正则表达式替换字符串开头或结尾的非单词(与[^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
参数并通过new RegExp()
构造函数传递['String', 'key']
对来声明正则表达式来对此进行概括。您仍然需要针对其他工件/大小写敏感度问题进行调整,但这可能会让您了解如何进行。
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);