将字符串转换为对象数组
Convert a string into an array of objects
目前我有这个字符串:
"Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah";
如何将它分成如下所示的对象数组:
[
{ type: 'string', value: 'Hello, I'm ' },
{ type: 'token', value: 'first' },
{ type: 'string', value: ' ' },
{ type: 'token', value: 'last' },
{ type: 'string', value: ', and I <3 being a ' },
{ type: 'token', value: 'occupation' },
{type: 'string', value: 'I am > blah'}
]
字符串的模式是,如果我们找到一个看起来像这样的单词:<%word%>,那么我们将它作为一个对象放入数组中,类型为 token。否则我们将其作为类型字符串放入。我的问题是我们如何在代码中实现它。
我很难形成将成为键 value
的 value
的短语。下面是我尝试实现的代码,但它是错误的。
我的想法是有一个单词变量,它是空的,当它通过字符串时,它会连接单词以形成阶段。一旦它发现它在 <%
和 %>
之间,它将被赋予一个类型 token
并推入 arrStr
数组。
但是有 2 个问题:1) 似乎使用这段代码,生成了从“H”到“He”到“Hel”到“Hell”再到“Hello”的字符串的每次迭代。 2)它似乎从未接触过令牌。 3) "hello" 中的第一个 "h" 被莫名其妙地省略了。
如何在不使用正则表达式的情况下执行此操作?
var str = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah";
var arr = str.split('<%');
var final = [], vala, thetype;
arr.forEach(val => {
vala=val.split('%>');
thetype='string';
if (vala.length>0) thetype='token';
final.push({type: thetype, value: vala[0]});
})
我确信正则表达式会是更好的解决方案,但我不知道。所以这是我的方法:
let txt = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah";
var arr = [];
txt.split("<%").forEach(x => {
if (x.includes("%>")) {
x.split("%>").forEach((y, i) => {
arr.push({type: i == 0 ? 'token' : 'string', value: y});
})
} else {
arr.push({type: 'string', value: x});
}
});
console.log(arr);
使用替换两次
让我们使用一些虚拟字符串替换 angular 括号以轻松拆分数据。
因此,我们将 <%
替换为 *#
,将 %>
替换为 *
。
那我们split
的数据就只有*
了。拆分后我们有以下数组
[
"Hello, I'm ",
"#first",
" ",
"#last",
", and I <3 being a ",
"#occupation",
". I am > blah",
]
因此,我们仅添加到左括号 angular 的额外 #
将帮助我们区分标记和字符串。
现在我们可以简单地映射这个数组并得到想要的结果。
注意:您可以使用您确定不会出现在字符串中的适当虚拟字符串。
const
str = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah",
res = str
.replace(/<%/g, "*#")
.replace(/%>/g, "*")
.split("*")
.map((v) =>
v[0] === "#"
? { type: "token", value: v.slice(1) }
: { type: "string", value: v }
);
console.log(res);
您可以像这样使用正则表达式解析字符串:
const input = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah";
const regex = /<%([^%]+)%>/g;
let result;
let parsed = [];
let lastIndex = 0;
while(result = regex.exec(input)) {
const { 1: match, index } = result;
parsed.push({ type: 'string', value: input.substring(lastIndex, index) });
parsed.push({ type: 'token', value: match });
lastIndex = index + match.length + 4;
}
parsed.push({ type: 'string', value: input.substring(lastIndex) });
console.log(parsed);
使用正则表达式:
const convertToObjectArr = (str = '') => {
const reg = /<%(.*?)%>/g;
let arr = [];
let index = 0, lastIndex = 0;
while (match = reg.exec(str)) {
index = match.index;
if(index > lastIndex) {
arr.push({ type: 'string', value: str.substring(lastIndex, index) });
}
lastIndex = reg.lastIndex;
arr.push({ type: 'token', value: str.substring(lastIndex-2, index+2) });
}
if (lastIndex == 0) {
arr.push({ type: 'string', value: str.substring(lastIndex) });
} else if (lastIndex < str.length) {
arr.push({ type: 'token', value: str.substring(lastIndex) });
}
return arr;
}
console.log( convertToObjectArr("Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah") );
console.log( convertToObjectArr("Hello") );
console.log( convertToObjectArr("Hello, I'm <%first%>") );
这是我的方法。如果你使用正则表达式,你可以简化很多(这基本上是正则表达式的确切用例)
target = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah"
const split = (el) => {
const parts = el.split('%>')
return [{type: 'token', value: parts[0]}, {type: 'string', value: parts[1]}]
}
const parts = target.split('<%')
.map(el =>
el.indexOf('%>') === -1
? {type: "string", value: el}
: split(el)
).flat()
console.log(parts)
您可以使用词法分析器来标记您的字符串。我在这个例子中使用了 moo:
const lexer =
moo.compile({ token: {match: /<%.+?%>/, value: raw => raw.slice(2, -2)}
, strlt: /.+?(?=<%)/
, strrt: /(?<=%>).+/ });
lexer.reset("Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah");
console.log(
[...lexer].map(({ type, value }) =>
({ type: (type === 'token' ? type : 'string')
, value }))
);
<script src="https://unpkg.com/moo@0.5.1/moo.js"></script>
目前我有这个字符串:
"Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah";
如何将它分成如下所示的对象数组:
[
{ type: 'string', value: 'Hello, I'm ' },
{ type: 'token', value: 'first' },
{ type: 'string', value: ' ' },
{ type: 'token', value: 'last' },
{ type: 'string', value: ', and I <3 being a ' },
{ type: 'token', value: 'occupation' },
{type: 'string', value: 'I am > blah'}
]
字符串的模式是,如果我们找到一个看起来像这样的单词:<%word%>,那么我们将它作为一个对象放入数组中,类型为 token。否则我们将其作为类型字符串放入。我的问题是我们如何在代码中实现它。
我很难形成将成为键 value
的 value
的短语。下面是我尝试实现的代码,但它是错误的。
我的想法是有一个单词变量,它是空的,当它通过字符串时,它会连接单词以形成阶段。一旦它发现它在 <%
和 %>
之间,它将被赋予一个类型 token
并推入 arrStr
数组。
但是有 2 个问题:1) 似乎使用这段代码,生成了从“H”到“He”到“Hel”到“Hell”再到“Hello”的字符串的每次迭代。 2)它似乎从未接触过令牌。 3) "hello" 中的第一个 "h" 被莫名其妙地省略了。
如何在不使用正则表达式的情况下执行此操作?
var str = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah";
var arr = str.split('<%');
var final = [], vala, thetype;
arr.forEach(val => {
vala=val.split('%>');
thetype='string';
if (vala.length>0) thetype='token';
final.push({type: thetype, value: vala[0]});
})
我确信正则表达式会是更好的解决方案,但我不知道。所以这是我的方法:
let txt = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah";
var arr = [];
txt.split("<%").forEach(x => {
if (x.includes("%>")) {
x.split("%>").forEach((y, i) => {
arr.push({type: i == 0 ? 'token' : 'string', value: y});
})
} else {
arr.push({type: 'string', value: x});
}
});
console.log(arr);
使用替换两次
让我们使用一些虚拟字符串替换 angular 括号以轻松拆分数据。
因此,我们将 <%
替换为 *#
,将 %>
替换为 *
。
那我们split
的数据就只有*
了。拆分后我们有以下数组
[
"Hello, I'm ",
"#first",
" ",
"#last",
", and I <3 being a ",
"#occupation",
". I am > blah",
]
因此,我们仅添加到左括号 angular 的额外 #
将帮助我们区分标记和字符串。
现在我们可以简单地映射这个数组并得到想要的结果。
注意:您可以使用您确定不会出现在字符串中的适当虚拟字符串。
const
str = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah",
res = str
.replace(/<%/g, "*#")
.replace(/%>/g, "*")
.split("*")
.map((v) =>
v[0] === "#"
? { type: "token", value: v.slice(1) }
: { type: "string", value: v }
);
console.log(res);
您可以像这样使用正则表达式解析字符串:
const input = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah";
const regex = /<%([^%]+)%>/g;
let result;
let parsed = [];
let lastIndex = 0;
while(result = regex.exec(input)) {
const { 1: match, index } = result;
parsed.push({ type: 'string', value: input.substring(lastIndex, index) });
parsed.push({ type: 'token', value: match });
lastIndex = index + match.length + 4;
}
parsed.push({ type: 'string', value: input.substring(lastIndex) });
console.log(parsed);
使用正则表达式:
const convertToObjectArr = (str = '') => {
const reg = /<%(.*?)%>/g;
let arr = [];
let index = 0, lastIndex = 0;
while (match = reg.exec(str)) {
index = match.index;
if(index > lastIndex) {
arr.push({ type: 'string', value: str.substring(lastIndex, index) });
}
lastIndex = reg.lastIndex;
arr.push({ type: 'token', value: str.substring(lastIndex-2, index+2) });
}
if (lastIndex == 0) {
arr.push({ type: 'string', value: str.substring(lastIndex) });
} else if (lastIndex < str.length) {
arr.push({ type: 'token', value: str.substring(lastIndex) });
}
return arr;
}
console.log( convertToObjectArr("Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah") );
console.log( convertToObjectArr("Hello") );
console.log( convertToObjectArr("Hello, I'm <%first%>") );
这是我的方法。如果你使用正则表达式,你可以简化很多(这基本上是正则表达式的确切用例)
target = "Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah"
const split = (el) => {
const parts = el.split('%>')
return [{type: 'token', value: parts[0]}, {type: 'string', value: parts[1]}]
}
const parts = target.split('<%')
.map(el =>
el.indexOf('%>') === -1
? {type: "string", value: el}
: split(el)
).flat()
console.log(parts)
您可以使用词法分析器来标记您的字符串。我在这个例子中使用了 moo:
const lexer =
moo.compile({ token: {match: /<%.+?%>/, value: raw => raw.slice(2, -2)}
, strlt: /.+?(?=<%)/
, strrt: /(?<=%>).+/ });
lexer.reset("Hello, I'm <%first%> <%last%>, and I <3 being a <%occupation%>. I am > blah");
console.log(
[...lexer].map(({ type, value }) =>
({ type: (type === 'token' ? type : 'string')
, value }))
);
<script src="https://unpkg.com/moo@0.5.1/moo.js"></script>