简体   繁体   中英

Filter or reduce array of strings by a substring

I have an array of strings:
let arr = ["cap:1", "col:red", "cap:3", "cap:1", "col:blue", "screen:yes"]
and I want to have a new array, with one item from each category of substrings( "cap", "col", "screen" ),the one with smallest index:
let newArray = ["cap:1","col:red","screen:yes"]
//"cap:1" from newArray is arr[0]
I tried this way:

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  
}

but it goes into infinite loop and the result is something like this: ["cap:1","col:red","col:red","col:red","col:red","col:red","col:red","col:red"... Could you please help me?
Thanks!

try with:

  • map to get category

  • filter to don't have duplicate

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

This is a great use case for Array.Reduce . You can reduce the many values of your array into a compact object by splitting the entries into key-values and simply taking the first entry for the given key. Something like this should work for you:

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

If you specifically need the results placed in an array, you can reassemble the parts into that format, but iteration over the resulting object should be reasonably efficient.

Here is an solution that might help you. First you need to map all the data so you get an key-value stream. This stream can then be reduced so only the first occurence will be saved.

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

It goes on infinite loop since there are two nested for loop and one of the nested for loop is iterating an ever increasing array. Instead you can have an object which will be act as a reference.

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

You could take a Set with an array of splitted first parts.

As result get an array from the 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);

Your logic has no way of determining that the current element's prefix was not found in newArr . Also, in the condition arr[i].split(":")[0].== c[j]:split(":") you are comparing a string to an array, which always returns true - string.== array.

May be you intended to write arr[i].split(":")[0].== c[j]:split(":")[0] which would still not give you the desired result.

You can do away with the inner loop and check each element against newArr using c.every(el =>....) as follows:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM