在每次出现特定子字符串时剪切数组中存在的 JS 字符串并附加到同一个数组

Posted

技术标签:

【中文标题】在每次出现特定子字符串时剪切数组中存在的 JS 字符串并附加到同一个数组【英文标题】:Cut JS string present in an array at every occurrance of a particular substring and append to same array 【发布时间】:2017-11-06 09:05:34 【问题描述】:

注意: 在这个时间点,我无法更好地措辞问题标题。如果有人能够更好地表达它,请继续!

我有什么:

var array = ["authentication.$.order", "difference.$.user.$.otherinformation", ... , ...] 

我需要什么:

["authentication", "authentication.$", "authentication.$.order",
"difference", "difference.$", "difference.$.user", "difference.$.user.$", 
"difference.$.user.$.otherinformation"]

基本上,无论我在哪里看到.$.,我都需要保留它,然后在.$. 出现之前附加所有内容以及.$ 出现之前的所有内容

示例:

difference.$.user.$.otherinformation 应该被解析为包含:

difference
difference.$
difference.$.user
difference.$.user.$
difference.$.user.$.otherinformation

我强烈感觉这里会涉及到某种递归,但还没有朝那个方向发展。

下面是我的实现,但不幸的是,当我的子字符串与.$. 的第一次出现匹配时,它会停止并且不会继续进一步检查同一字符串中.$. 的其他出现。

我怎样才能最好地结束这个?

当前有缺陷的实现:

for(var i=0; i<array.length; i++)
    //  next, replace all array field references with $ as that is what autoform's pick() requires
    //  /\.\d+\./g,".$." ==> replace globally .[number]. with .$.    
    array[i] = array[i].replace(/\.\d+\./g,".$.");
        if(array[i].substring(0, array[i].lastIndexOf('.$.')))
            console.log("Substring without .$.  " + array[i].substring(0, array[i].indexOf('.$.')));
            console.log("Substring with .$ " + array[i].substring(0, array[i].indexOf('.$.')).concat(".$"));
            array.push(array[i].substring(0, array[i].indexOf('.$.')).concat(".$"));
            array.push(array[i].substring(0, array[i].indexOf('.$.')));
            
        
    // finally remove any duplicates if any
    array = _.uniq(array);

【问题讨论】:

【参考方案1】:

使用一个简单的for 循环,如下所示:

var str = "difference.$.user.$.otherinformation";
var sub, initial = "";
var start = 0;
var pos = str.indexOf('.');
for (; pos != -1; pos = str.indexOf('.', pos + 1)) 
  sub = str.substring(start, pos);
  console.log(initial + sub);
  initial += sub;
  start = pos;

console.log(str);

【讨论】:

【参考方案2】:

一个功能单一的衬里可以是;

var array  = ["authentication.$.order", "difference.$.user.$.otherinformation"],
    result = array.reduce((r,s) => r.concat(s.split(".").reduce((p,c,i) => p.concat(i ? p[p.length-1] + "." + c : c), [])), []);
console.log(result);

【讨论】:

迄今为止在紧凑性方面最短的答案,但在可理解性方面却很复杂。您能解释一下这实际上是如何工作的吗? 如果数组包含如下值怎么办:"www.example.com."? @hindmost - 好问题,但我的初始数组永远不会包含以 . 结尾的东西,所以我想可以安全地假设。【参考方案3】:

这个问题实际上不需要递归。您可以将常规循环与子循环一起使用。

你只需要:

    将数组中的每个出现拆分为子字符串; 从这些子字符串中构建一系列累积值; 用这个系列替换数组的当前元素。

此外,为了使替换正常工作,您必须以相反的顺序迭代数组。顺便说一句,在这种情况下,您不需要删除数组中的重复项。

所以代码应该是这样的:

var array = ["authentication.$.order", "difference.$.user.$.otherinformation"];

var SEP = '.$.';
for (var i = array.length-1; i >= 0; i--)
    var v = array[i];
    var subs = v.replace(/\.\d+\./g, SEP).split(SEP)
    if (subs.length <= 1) continue;
    var acc = subs[0], elems = [acc];
    for (var n = subs.length-1, j = 0; j < n; j++) 
        elems[j * 2 + 1] = (acc += SEP);
        elems[j * 2 + 2] = (acc += subs[j]);
    
    array.splice.apply(array, [i, 1].concat(elems));

console.log(array);

【讨论】:

我在 chrome 控制台中试了一下这段代码 sn-p 以了解发生了什么。但是,输出似乎与所需的有所不同。输出:,difference.$.,difference.$.difference,difference.$.difference.$.,difference.$.difference.$.user @blueren 抱歉,我忘了用subs[0] 初始化elems。现在可以了【参考方案4】:

你可以使用reduce如下:

 const dat = ["authentication.$.order", "difference.$.user.$.otherinformation"];

 const ret = dat.reduce((acc, val) => 
    const props = val.split('.');
    let concat = '';
    return acc.concat(props.reduce((acc1, prop) => 
      concat+= (concat ? '.'+ prop : prop);
      acc1.push(concat);
      return acc1;
    , []));
 , [])

 console.log(ret);

【讨论】:

【参考方案5】:

我使用正则表达式来抓取所有内容,直到最后一次出现 .$ 并将其切碎,直到什么都没有。最后反转。

let results = [];
let found = true;

const regex = /^(.*)\.\$/g;
let str = `difference.\$.user.\$.otherinformation`;
let m;

results.push(str);
while(found) 
    found = false;
    while ((m = regex.exec(str)) !== null) 
        // This is necessary to avoid infinite loops with zero-width matches
        if (m.index === regex.lastIndex) 
            regex.lastIndex++;
        

        if(m.length > 0) 
            found = true;
            results.push(m[0]);
            str = m[1];
        
    

results.push(str);
results = results.reverse();
// Concat this onto another array and keep concatenating for the other strings
console.log(results);

你只需要在你的数组上循环,将结果存储在一个临时数组中,然后继续将它们连接到一个最终数组中。

https://jsfiddle.net/9pa3hr46/

【讨论】:

这有点不对...结果是:difference,difference.$,difference.$.user.$,difference.$.user.$.otherinformation 注意difference.$.user 已被跳过。【参考方案6】:

你可以在你的数组循环中使用这个函数。

var test = "difference.$.user.$.otherinformation";

function toArray(testString) 
  var testArr = testString.split(".")

  var tempString = "";
  var finalArray = [];

  for (var i = 0; i < testArr.length; i++) 

    var toTest = testArr[i];

    if (toTest == "$") 
      tempString += ".$"
     else 
      if (i != 0) 
        tempString += ".";
      

      tempString += toTest;
    

    finalArray.push(tempString)

   
  return finalArray;

console.log(toArray(test))

【讨论】:

以上是关于在每次出现特定子字符串时剪切数组中存在的 JS 字符串并附加到同一个数组的主要内容,如果未能解决你的问题,请参考以下文章

关于JS如何判断一个字符串中存在多少个相同的数据?

在第 n 次出现字符时剪切字符串

检查字符串是不是存在子字符串

检查多维数组的任何子数组中的特定键是不是存在特定值

Julia:数组是不是包含特定的子数组

jquery如何输出数组中某个特定值