![](/img/trans.png)
[英]Split String Into Array Elements Based On Punctuation In String - JavaScript
[英]How to split the String based on array elements into array retaining the array the split word in javascript
我有一个字符串
sReasons = "O9C2700021Not eligible for SDWCEOC3900015Service upgradeHJC3900015Service upgradeJ8C5000016Delivery Attempt";
我需要根据分隔符数组拆分上面的字符串
const separator = ["O9", "EO", "HJ", "J8"];
其中前 2 个字符 (O9) 代表网络代码,接下来 4 个另一个代码 (C270) & 下 4 个字符 (0021) 不符合 SDWC 条件的字符串长度
其中分隔码是唯一的,有2个大写字母,除inEligType
textMessage
中不会重复
我需要创建一个格式为 json
{
{inEligType: "O9", msgCode: "C270", msgLen: "0021", textMsg: "Not eligible for SDWC"},
{inEligType: "EO", msgCode: "C390", msgLen: "0015", textMsg: "Service upgrade"},
{inEligType: "HJ", msgCode: "C390", msgLen: "0015", textMsg: "Service upgrade"},
{inEligType: "J8", msgCode: "C500", msgLen: "0016", textMsg: "Delivery Attempt"}
}
我基本上没有根据给定的数组拆分字符串本身,我尝试了以下
sReasons = "O9C2700021Not eligible for SDWCEOC0900015Service upgradeHJC3900015Service upgradeJ8C5HJ0016Delivery Attempt";
const separator = ["O9", "EO", "HJ", "J8"];
function formatReasons(Reasons: string) {
var words: any[] = Reasons.split(this.spearator);
for(let word in words)
{
console.log(word) ;
}
}
var result = formatReasons(sHdnReasonsCreate);
console.log("Returned Result: "+result);
但它给了我结果
["O9C2700021Not eligible for SDWCEOC0900015Service upgradeHJC3900015Service upgradeJ8C5HJ0016Delivery Attempt"]length: 1__proto__: Array(0)
Returned Address is: undefined
我的基于正则表达式的方法:
sReasons = "O9C2700021Not eligible for SDWCEOC0900015Service upgradeHJC3900015Service upgradeJ8C5HJ0016Delivery Attempt";
const separator = ["O9", "EO", "HJ", "J8"];
// build the regex based on separators
let regexPattern = '^';
separator.forEach(text => {
regexPattern += `${text}(.*)`;
});
regexPattern += '$';
// match the reasons
let r = new RegExp(regexPattern);
let matches = sReasons.match(r);
// prepare to match each message
let msgMatcher = new RegExp('^(?<msgCode>.{4})(?<msgLen>.{4})(?<textMsg>.*)$');
let output = [];
for (let i=1; i<matches.length; i++) {
// match the message
const msg = matches[i].match(msgMatcher);
// store
let item = msg.groups;
item.inEligType = separator[i-1];
output.push(item);
}
console.log(JSON.stringify(output, null, 2));
生产
[
{
"msgCode": "C270",
"msgLen": "0021",
"textMsg": "Not eligible for SDWC",
"inEligType": "O9"
},
{
"msgCode": "C090",
"msgLen": "0015",
"textMsg": "Service upgrade",
"inEligType": "EO"
},
{
"msgCode": "C390",
"msgLen": "0015",
"textMsg": "Service upgrade",
"inEligType": "HJ"
},
{
"msgCode": "C5HJ",
"msgLen": "0016",
"textMsg": "Delivery Attempt",
"inEligType": "J8"
}
]
很可能textMsg
字段或任何其他字段永远不会包含您用于inEligType
字段的两个字母字符串。 但你绝对确定吗? 在我看来,数据格式确实希望有人通过特定长度的子字符串来解析它; 如果您可以根据分隔符进行拆分,为什么还要有一个msgLen
字段? 如果将来inEligType
代码列表发生变化怎么办?
由于这些原因,我强烈建议您通过 substring 长度而不是分隔符匹配来解析。 这是一种可能的方法:
function formatReasons(reasons: string) {
const ret = []
while (reasons) {
const inEligType = reasons.substring(0, 2);
reasons = reasons.substring(2);
const msgCode = reasons.substring(0, 4);
reasons = reasons.substring(4);
const msgLen = reasons.substring(0, 4);
reasons = reasons.substring(4);
const textMsg = reasons.substring(0, +msgLen);
reasons = reasons.substring(+msgLen);
ret.push({ inEligType, msgCode, msgLen, textMsg });
}
return ret;
}
您可以验证它是否为您的示例sReasons
字符串生成了预期的 output:
const formattedReasons = formatReasons(sReasons);
console.log(JSON.stringify(formattedReasons, undefined, 2));
/* [
{
"inEligType": "O9",
"msgCode": "C270",
"msgLen": "0021",
"textMsg": "Not eligible for SDWC"
},
{
"inEligType": "EO",
"msgCode": "C090",
"msgLen": "0015",
"textMsg": "Service upgrade"
},
{
"inEligType": "HJ",
"msgCode": "C390",
"msgLen": "0015",
"textMsg": "Service upgrade"
},
{
"inEligType": "J8",
"msgCode": "C5HJ",
"msgLen": "0016",
"textMsg": "Delivery Attempt"
}
] */
请注意,上面的实现不检查字符串的格式是否正确; 现在,如果你把垃圾送进去,你就会把垃圾拿出来。 如果您想要更多的安全性,您可以进行运行时检查并抛出错误,例如,意外地运行reasons
字符串的末尾,或者找到不代表数字的msgLen
字段。 并且可以进行重构,这样就不会重复像const s = reasons.substring(0, n); reasons = reasons.substring(n)
这样的代码。 const s = reasons.substring(0, n); reasons = reasons.substring(n)
。 但是基本算法就在那里。
RegExp 的另一种选择,代码更少
// Your data const data = "O9C2700021Not eligible for SDWCEOC3900015Service upgradeHJC3900015Service upgradeJ8C5000016Delivery Attempt"; // Set your data splitters from array const spl = ["O9", "EO", "HJ", "J8"].join('|'); // Use regexp to parse data const results = []; data.replace(new RegExp(`(${spl})(\\w{4})(\\w{4})(.*?)(?=${spl}|$)`, 'g'), (m,a,b,c,d) => { // Form objects and push to res results.push({ inEligType: a, msgCode: b, msgLen: c, textMsg: d }); }); // Result console.log(results);
第一种方法,基于捕获split
消耗的正则表达式的组,由助手 function 处理,最后reduce
d 减少到预期结果......
function chunkRight(arr, chunkLength) { const list = []; arr = [...arr]; while (arr.length >= chunkLength) { list.unshift( arr.splice(-chunkLength) ); } return list; } // see also... [https://regex101.com/r/tatBAB/1] // with eg // (?<inEligType>O9|EO|HJ|J8)(?<msgCode>\w{4})(?<msgLen>\d{4}) //... or... // (O9|EO|HJ|J8)(\w{4})(\d{4}) // function extractStatusItems(str, separators) { const regXSplit = RegExp(`(${ separators.join('|') })(\\w{4})(\\d{4})`); const statusValues = String(str).split(regXSplit).slice(1); const groupedValues = chunkRight(statusValues, 4); return groupedValues.reduce((list, [inEligType, msgCode, msgLen, textMsg]) => list.concat({ inEligType, msgCode, msgLen, textMsg }), [] ); } const statusCode = 'O9C2700021Not eligible for SDWCEOC3900015Service upgradeHJC3900015Service upgradeJ8C5000016Delivery Attempt'; console.log( `statusCode... ${ statusCode }...`, extractStatusItems(statusCode, ['O9', 'EO', 'HJ', 'J8']) );
.as-console-wrapper { min-height: 100%;important: top; 0; }
...其次是第二种方法,几乎完全基于捕获命名组的正则表达式,由matchAll
消耗,最后map
进入预期结果...
// see also... [https://regex101.com/r/tatBAB/2] // with eg // (?<inEligType>O9|EO|HJ|J8)(?<msgCode>\w{4})(?<msgLen>\d{4})(.*?)(?<textMsg>.*?)(?=O9|EO|HJ|J8|$) // function extractStatusItems(str, separators) { separators = separators.join('|'); const regXCaptureValues = RegExp( `(?<inEligType>${ separators })(?<msgCode>\\w{4})(?<msgLen>\\d{4})(.*?)(?<textMsg>.*?)(?=${ separators }|$)`, 'g' ); return [...String(str).matchAll(regXCaptureValues) ].map( ({ groups }) => ({...groups }) ); } const statusCode = 'O9C2700021Not eligible for SDWCEOC3900015Service upgradeHJC3900015Service upgradeJ8C5000016Delivery Attempt'; console.log( `statusCode... ${ statusCode }...`, extractStatusItems(statusCode, ['O9', 'EO', 'HJ', 'J8']) );
.as-console-wrapper { min-height: 100%;important: top; 0; }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.