【问题标题】:How to remove strings which extends original string from JavaScript array?如何从 JavaScript 数组中删除扩展原始字符串的字符串?
【发布时间】:2022-07-01 16:04:31
【问题描述】:

我有以下数组: ['total.color.violet', 'total.color.violet.truefont', 'total.color.red', 'total.color.red.circle', 'total.color.red.circle.elefant', 'total.color.blue', 'total.color.yellow', 'total.color.yellow.dotted']。正如我们所见,所有字符串都有常量部分 total.color 和可变部分。 我需要得到下一个结果:['total.color.violet', 'total.color.red', 'total.color.blue', 'total.color.yellow'] - 删除复杂度超过“第三级”的字符串,只留下“第二级”复杂度的字符串。 如果可能的话,请看一下这个算法并给我任何提示。

【问题讨论】:

  • 到目前为止你有什么尝试?
  • 请提供您想要的示例输出。
  • @TwittorDrive 我用一行代码添加了一个答案。希望这会有所帮助。

标签: javascript node.js arrays string algorithm


【解决方案1】:

一个相对简单的“点数”案例。

这里我使用正则表达式来确定字符串中. 的出现次数。 'g' 标志返回字符串中的所有匹配项。

match可以在不匹配的情况下返回null,所以|| []保证有一个长度为零的数组,这样我们就可以访问属性length

所有带有 2 个或更少点的条目都保留在过滤后的数组中。

let values = ['total.color.violet', 'total.color.violet.truefont', 'total.color.red', 'total.color.red.circle', 'total.color.red.circle.elefant', 'total.color.blue', 'total.color.yellow', 'total.color.yellow.dotted']

const output = values
    .filter(value => (value.match(/\./g) || []).length <= 2)

console.log(output)

【讨论】:

    【解决方案2】:

    使用a Set 删除欺骗,a regex 使用match 查找字符串。

    const arr=['total.color.violet','total.color.violet.truefont','total.color.red','total.color.red.circle','total.color.red.circle.elefant','total.color.blue','total.color.yellow','total.color.yellow.dotted'];
    
    const set = new Set();
    const re = /^total.color.[a-z]+/;
    
    for (const str of arr) {
      set.add(str.match(re)[0]);
    }
    
    console.log([...set]);

    【讨论】:

      【解决方案3】:

      给你。只需使用'level1.level2.level3'.split('.') 将其分解为一个由. 分隔的数组。

      您可以使用 Set() 轻松删除重复项(区分大小写),然后将其转换回数组。

      let values = ['total.color.violet', 'total.color.violet.truefont', 'total.color.red', 'total.color.red.circle', 'total.color.red.circle.elefant', 'total.color.blue', 'total.color.yellow', 'total.color.yellow.dotted'];
      
      let level123 = [];
      let colorsOnly = [];
      for(let value of values){
          // Get each level (seperated by '.')
          let level = value.split('.');
          
          // Add each level (1-3)
          level123.push(`${level[0]}.${level[1]}.${level[2]}`);
          
          // Add only the colors
          colorsOnly.push(level[2]);
      }
      
      // Remove duplication
      level123 = [...new Set(level123)];
      colorsOnly = [...new Set(colorsOnly)]
      
      // Show the newly formatted values
      console.log("Levels 1-3: ", level123);
      console.log("Colors only: ", colorsOnly);

      【讨论】:

      • 这不是 OP 想要的输出。
      • @Andy Ah,很难准确理解他的要求。重读后……现在我相信他只是想要字符串中的颜色?我添加了一个colorsOnly 值——得到他的要求。
      • ['total.color.violet', 'total.color.red', 'total.color.blue', 'total.color.yellow'] 没有重复。
      • 我已经使用Set()更新了删除重复项的答案
      【解决方案4】:

      最简单的方法是根据每个单词调用 split 的长度使用过滤器。 javascript split

      一种简单的方法是遍历数组并删除“total.color”。使用切片或替换方法从每个字符串中提取部分。然后,在第二次循环中,如果字符串包含“.”

      有3个以上的级别:

      【讨论】:

        【解决方案5】:

        我们可以通过首先找到以您的前缀开头的那些元素,然后为每个元素切掉前缀(加上一个额外的 '.'),在每个 ',' 处拆分它,获取第一个结果并附加它到前缀(再次加上'.'。)然后我们通过将结果包装在一个集合中并将其转回一个数组来获取这些唯一集合。它可能看起来像这样:

        const nextLevel = (strings, prefix) => [...new Set (
          strings .filter (s => s .startsWith (prefix + '.')) 
                  .map (s => prefix + '.' + s .slice (prefix .length + 1) .split ('.') [0])
        )]
        
        const strings1 = ['total.color.violet', 'total.color.violet.truefont', 'total.color.red', 'total.color.red.circle', 'total.color.red.circle.elefant', 'total.color.blue', 'total.color.yellow', 'total.color.yellow.dotted']
        const prefix1 = 'total.color'
        console .log (nextLevel (strings1, prefix1))
        
        const strings2 = ['telex.fast', 'telex.fast.line.hope', 'total.fast.ring', 'telex.slow', 'total.slow.motion']
        const prefix2 = 'telex'
        console .log (nextLevel (strings2, prefix2))
        .as-console-wrapper {max-height: 100% !important; top: 0}

        一个有趣的替代方法是不提供前缀作为初始参数,而是直接从字符串中提取它。我们可以这样做:

        const leveled = (ss, prefix = ss .reduce ((x, y, _, __, [a, b] = y .length < x .length ? [x, y] : [y, x]) => 
          a .slice (0, [...a] .findIndex ((_, i) => a [i] !== b [i]))
        )) => [...new Set (ss .map (s => s .substring (prefix .length) .split ('.') [0]))] .map (s => prefix + s)
        
        const input1 = ['total.color.violet', 'total.color.violet.truefont', 'total.color.red', 'total.color.red.circle', 'total.color.red.circle.elefant', 'total.color.blue', 'total.color.yellow', 'total.color.yellow.dotted']
        console .log (leveled (input1))
        
        const input2 =['telex.fast', 'telex.fast.line.hope', 'total.fast.ring', 'telex.slow', 'total.slow.motion']
        console .log (leveled (input2))
        .as-console-wrapper {max-height: 100% !important; top: 0}

        但这不会以与上述相同的方式捕获telex 示例,因为它考虑了所有级别,并且没有公共前缀。上面的例子给了我们['telex.fast', 'telex.slow'],这个例子会给我们['telex', 'total']。哪个更合适取决于您的需求。

        我们还应该注意,由于此技术使用没有初始值的reduce,因此它不适用于空值列表。

        最后,应该清理这个版本,提取辅助函数。我可能更喜欢这样写:

        const sharedPrefix = (a, b) => a.length < b .length 
          ? sharedPrefix (b, a) 
          : a .slice (0, [...a] .findIndex ((_, i) => a [i] !== b [i]))
        
        const commonPrefix = (ss) => ss .reduce (sharedPrefix)
        
        const leveled = (ss, prefix = commonPrefix (ss)) =>
          [...new Set (ss .map (s => s .substring (prefix .length) .split ('.') [0]))] .map (s => prefix + s)
        

        (这几乎没有经过测试。)

        【讨论】:

        • Scott Sauyet,用reduce 方法的分辨率太酷了,谢谢。我会在测试后得到它。
        【解决方案6】:

        您可以使用Array.filter() 方法通过一行代码轻松实现。

        演示

        const arr = [
          'total.color.violet',
          'total.color.violet.truefont',
          'total.color.red',
          'total.color.red.circle',
          'total.color.red.circle.elefant',
          'total.color.blue',
          'total.color.yellow',
          'total.color.yellow.dotted'
        ];
        
        const prefix = 'total.color';
        
        const res = arr.filter(item => item.indexOf(prefix) === 0).filter(item => item.split('.').length === 3);
        
        console.log(res);

        【讨论】:

          【解决方案7】:

          你可以数点数。 这里我没有使用正则表达式来确定.的数量

          const arr = ['total.color.violet', 'total.color.violet.truefont', 'total.color.red', 'total.color.red.circle', 'total.color.red.circle.elefant', 'total.color.blue', 'total.color.yellow', 'total.color.yellow.dotted'];
          
          const dotCount = (str) => {
              let count = 0;
              for (let i=0; i<str.length; i++) {
                  count += (str[i] == '.' ? 1 : 0);
              }
              return count;
          }
          
          const filterArray = (arr) => {
              let filtered = []
              arr.forEach(el => {
                  if (dotCount(el) <= 2) {
                      filtered.push(el);
                  }
              })
              
              return filtered;
          }
          
          console.log(filterArray(arr))

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-01-16
            • 1970-01-01
            • 1970-01-01
            • 2016-01-01
            • 1970-01-01
            • 2016-05-30
            • 2018-09-22
            相关资源
            最近更新 更多