通过子字符串过滤或减少字符串数组

Posted

技术标签:

【中文标题】通过子字符串过滤或减少字符串数组【英文标题】:Filter or reduce array of strings by a substring 【发布时间】:2022-01-13 13:32:04 【问题描述】:

我有一个字符串数组:let arr = ["cap:1", "col:red", "cap:3", "cap:1", "col:blue", "screen:yes"] 我想要一个新数组,每个子字符串类别中有一个项目(“cap”,“col”,“screen”),索引最小的一个:let newArray = ["cap:1","col:red","screen:yes"] //"cap:1" from newArray is arr[0] 我试过这样:

const newArr = (arr) => 
    let c= []
    let c = [...c, arr[0]]  
    for(let i = 1; i<arr.length; i++)
        for (let j=0; j<c.length; j++)
            if(arr[i].split(":")[0] !== c[j].split(":"))
                c = [...c, arr[i]]
            
        
    
    return c  

但它进入了无限循环,结果是这样的:["cap:1","col:red","col:red","col:red","col:red","col:red","col:red","col:red"... 你能帮帮我吗? 谢谢!

【问题讨论】:

【参考方案1】:

尝试:

map 获取类别

filter 没有重复

arr.map(oneElement => oneElement.split(":")[0])
   .filter((elem, index, a) => index === a.indexOf(elem));

let arr = ["cap:1", "col:red", "cap:3", "cap:1", "col:blue", "screen:yes"];

let categ =  arr.map(oneElement => oneElement.split(":")[0]).filter((elem, index, a) => index === a.indexOf(elem));

console.log(categ);
     

【讨论】:

【参考方案2】:

这是Array.Reduce 的一个很好的用例。您可以通过将条目拆分为键值并简单地获取给定键的第一个条目来将数组的许多值减少为一个紧凑的对象。像这样的东西应该适合你:

const firstOfGroup = arr => arr.reduce((result, currentValue) => 
   const parts = currentValue.split(':');
   const key = parts[0];
   const value = parts[1];
   if (!result.hasOwnProperty(key)) 
      result[key] = value;
   
   return result;
);

如果您特别需要将结果放在一个数组中,您可以将这些部分重新组合成该格式,但是对结果对象的迭代应该是相当有效的。

【讨论】:

【参考方案3】:

这里有一个可能对您有所帮助的解决方案! 首先,您需要映射所有数据,以便获得键值流。然后可以减少此流,以便只保存第一次出现。

let newArr = data.map(function(item)
        return item.split(":")
    ).reduce(function(acc, curr)
        if(acc[curr[0]] === undefined)
            acc[curr[0]] = curr[1]
        
        return acc
    )

【讨论】:

【参考方案4】:

它继续无限循环,因为有两个嵌套的 for 循环,其中一个嵌套的 for 循环正在迭代一个不断增加的数组。相反,您可以拥有一个对象作为参考。

let arr = ["cap:1", "col:red", "cap:3", "cap:1", "col:blue", "screen:yes"];
const newArr = (arr) => 
  let c = [];
  const suffixObj = ;
  for (let i = 0; i < arr.length; i++) 
    const getPrefix = arr[i].split(":")[0];
    if (!suffixObj.hasOwnProperty(getPrefix)) 
      c.push(arr[i]);
      suffixObj[getPrefix] = true
    
  

  return c
;

console.log(newArr(arr))

【讨论】:

【参考方案5】:

您可以使用Set,其中包含一组拆分的第一部分。

结果从集合中得到一个数组。

const
    array = ["cap:1", "col:red", "cap:3", "cap:1", "col:blue", "screen:yes"],
    types = [...new Set(array.map(s => s.split(':', 1)[0]))];

console.log(types);

【讨论】:

【参考方案6】:

您的逻辑无法确定在newArr 中找不到当前元素的前缀。此外,在条件 arr[i].split(":")[0] !== c[j].split(":") 中,您将字符串与数组进行比较,该数组始终返回 true - string !== array。

您可能打算写arr[i].split(":")[0] !== c[j].split(":")[0],但仍然不会给您想要的结果。

您可以取消内部循环并使用c.every(el =&gt; !...) 对照newArr 检查每个元素,如下所示:

let arr = ["cap:1", "col:red", "cap:3", "cap:1", "col:blue", "screen:yes"];

const newArr = (arr) => 
    let c = [arr[0]]; 
    for(let i = 1; i<arr.length; i++) 
        if( c.every(el => !arr[i].startsWith( el.split(':')[0] )) ) 
            c = [ ...c, arr[i] ];
        
    
    return c; 


console.log( newArr( arr ) );

【讨论】:

以上是关于通过子字符串过滤或减少字符串数组的主要内容,如果未能解决你的问题,请参考以下文章

使用子字符串过滤字符串数组

使用子字符串作为条件过滤子文档数组

在 Mongoose/MongoDB 的文档中过滤数组、子文档、数组、文档

React JS:按字符串过滤数组

Java 通过另一个大小为 n 的布尔数组过滤数组

如何在字符串数组中过滤或查找字符串