简体   繁体   中英

JavaScript Join Identical Adjacent Elements in an Array

Input:

['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e']

Desired output:

['aaa', 'bb', 'ccc', 'd', 'ee']

Is this possible?

Edit: I forgot to mention that my previous attempt (for another example) failed, and I cannot figure out why:

let newArr = []
let last
let current
for (var i = 0; i < arr.length; i ++) {
    last = last || isCurrencyArr[i]
    current = isCurrencyArr[i]
    let str = ''
    if (last === current) {
        str += arr[i]
    } else {
        newArr.push(str)
        str = ''
    }
    last = isCurrencyArr[i]
}

Your example has a few hiccups. It redeclares str inside each iteration, therefore it only ever pushes empty strings. Also, it pushes the previous string when it comes across a new item, but it doesn't account for scenarios where the last items are the same, as in your example with the letter e .


If you're joining alike elements together, regardless of position...

Instead, you could use reduce() and spread syntax for object literals to build an object that keeps track of the occurrences of each item.

The object after reduce() looks like this:

{ a: "aaa", b: "bb", c: "ccc", d: "d", e: "ee" }

Once that object is built, all we have to do is create an array from the values using Object.values() .

 const arr = ['a', 'b', 'a', 'c', 'b', 'a', 'e', 'd', 'c', 'e', 'c']; let items = arr.reduce((acc,i) => acc[i] ? {...acc, [i]: acc[i]+i } : {...acc, [i]: i }, {}); let result = Object.values(items); console.log(result);


If you only want to join adjacent alike elements...

The example below uses a slightly similar approach to the above, however this reduce() outputs a string. The logic is similar to your own example: if the previous item is the same, add it to a string. If it is not , separate it and keep going.

The result is something like this: aaa|bb|ccc|d|ee . To turn that into an array, we just need to do split("|") .

 const arr = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e']; let result = arr .reduce((acc,i,idx,a) => (a[idx-1] === i || idx===0) ? acc+i : acc+"|"+i, "") .split("|"); console.log(result);

Using Array#reduce , spread syntax , and Map .

 const data = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e']; const res = [...data.reduce((a,c)=>{ return a.set(c, (a.get(c)||"") + c); }, new Map()).values()]; console.log(res);

Algo for strictly adjacent elements.

 const data = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e']; const res = []; for(let i = 0; i < data.length; i++){ const c = data[i]; let str = c; for(let j = i + 1; j < data.length && c === data[j]; j++,i++){ str += c; } res.push(str); } console.log(res);

This can be a solution to join adjacent elements :

 const arr = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e']; const resp = arr.reduce((a, e) => { if(a.length === 0) return a.concat(e); if(e === a[a.length - 1].split('').reverse()[0]) { a[a.length - 1] = a[a.length - 1].split('').concat(e).join(''); return a; } return a.concat(e); }, []) console.log(resp);

Something like this should work:

   function simplify(arr) {
        let current = arr[0];
        let final_arr = [];
        let accumulated = current;
        for (let i = 1; i < arr.length; i += 1) {
            if (current === arr[i]) {
                accumulated += arr[i];
            } else {
                final_arr.push(accumulated)
                current = arr[i];
                accumulated = current;
            }
        }
        final_arr.push(accumulated);
        return final_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