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

Filter or reduce array of strings by a substring

我有一个字符串数组:
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"... 你能帮帮我吗?
谢谢!

这是 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;
});

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

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

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
    })

它继续无限循环,因为有两个嵌套的 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))

您可以使用一个 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);

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

可能是您打算编写 arr[i].split(":")[0] !== c[j].split(":")[0],但仍然无法为您提供所需的结果。

您可以取消内部循环并使用 c.every(el => !...) 根据 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 ) );