簡體   English   中英

用javascript查找數組中連續的dups,對其求和並重申的最簡潔方法是什么?

[英]What's the most concise way in javascript to find consecutive dups in an array, sum them up and reiterate?

我有一個數組:

const myArr = [1, 1, 1, 3, 2, 2, 4, 3];

如果將它傳遞給函數,它將產生如下輸出:

//result: [2, 1, 3, 8, 3]

連續的前兩個1 s和2 s是連續的重復項,因此將它們相加。

前兩個連續的1變為2因此現在不匹配。

連續的2變成4因此它與下一個運行編號匹配,並再次求和,結果為8

盡管3 s是重復的,但由於它們不是連續的,所以我們不對其進行總結


獎金

  • 如果有人可以使用javascript的數組函數mapreduce演示這一點,那就太好了。

  • 沒有任何遞歸就可能嗎? 有人提到了它的可能,那么如果不使用遞歸的話我會很好


編輯

在此處添加此內容是因為有些人已經提供了答案。

如果是:

const myArr = [1, 1, 1, 1];
// result: [4]

const myArr = [1, 1, 1, 1, 3, 2, 2, 4, 3];
// result: [4, 3, 8, 3]

另一個我沒想到的有趣案例:

const myArr = [1, 1, 2, 2];
//result [4, 2] instead of [2,4]

進行更改后,它應立即對照新陣列進行檢查

假設僅將其用於數字數組,則此操作非常簡單,可以進行reduce。

function duplicateAddition(input) {
    var last;
    var result = input;
    do {
        last = result;
        result = last.reduce(function (carry, item) {
            if (carry[carry.length - 1] == item) {
                carry[carry.length - 1] *= 2;
            } else {
                carry.push(item);
            }
            return carry;
        }, []);
    } while (last.length != result.length);
    return result;
}

假設數組總是包含數字,那么我能想到的最簡潔的是

function merge(arr) {
    var x = String(arr),
        y = x.replace(/([^,]),\1/, (_,m)=>2*m);
    return x.length == y.length ? y.split(",").map(Number) : merge(y);
}

如果要避免尾部遞歸,將其轉換為循環很簡單:

function merge(arr) {
    var y = String(arr);
    do {
        var x = y;
        y = x.replace(/([^,]),\1/, (_,m)=>2*m);
    } while(x.length != y.length)
    return y.split(",").map(Number);
}

要么

function merge(arr) {
    for (var x=String(arr), y=""; x.length!=y.length; x=y.replace(/([^,]),\1/, (_,m)=>2*m))
        y=x;
    return x.split(",").map(Number);
}

順便說一句,要更改算法的行為以從[2, 4] 1、1、2、2 [2, 4]獲得[2, 4]而不是[4, 2] [1, 1, 2, 2] (即,找到所有重復項並在重復之前求和),您只需要將/g lobal標志添加到正則表達式。

此解決方案使用遞歸生成器。 它具有的優點是,它幾乎說出了什么意思,並且做了什么。

 function* x([first, second, ...rest]) { if (first !== undefined) { if (first !== second) yield first; else second *= 2; yield* x([second, ...x(rest)]); } } function test(a) { console.log(Array.from(x(a))); } test([1, 1, 1, 3, 2, 2, 4, 3]); test([1, 1, 1, 1]); test([1, 1, 2, 2]); 

在此解決方案中,輸入[1, 1, 2, 2]產生[2, 4] 這是因為邏輯將2, 2貪婪地折疊為4 ,然后與1, 1產生的2不匹配。 如果不需要此行為,則將上面的行更改為:

yield* x([second, ...rest]);

這是一個簡單的游戲,從數組a移到推送數組b 因此,如果a[0] === a[1] ,則從數組a取出前兩個項,求和並將其推入數組b但是如果a[0] !== a[1]則僅取第一個項項目並將其推入數組b 但是,在我們推中間值(代碼段下面的t )之前,我們檢查了數組b的最后一項,看它是否等於中間值。 如果它們相等,我們不只是將臨時( t )推到b就將數組b的最后一項加倍。

然后進行尾調用優化的遞歸調用。

 function sumAndReduce(a, b = []){ var t = 0; if (!a.length) return b; t = a[0] === a[1] ? a.splice(0,2).reduce((p,c) => p+c) : a.splice(0,1)[0]; b[b.length-1] === t ? b[b.length-1] += t : b.push(t); return sumAndReduce(a,b); } var myArr = [1, 1, 1, 3, 2, 2, 4, 3], result = sumAndReduce(myArr); console.log(JSON.stringify(result)); console.log(JSON.stringify(sumAndReduce([1, 1, 1, 1]))); console.log(JSON.stringify(sumAndReduce([1, 1, 2, 2]))); 

好吧...如果您不希望遞歸,即使它是優化的尾調用,那么將上述代碼轉換為帶有while循環的迭代代碼也很簡單。 我留給你..!

因此,我無法確定您根據輸入[1,1,2,2]發出的請求是否違反了初始條件,但這也是上述代碼的修改版本,以符合要求。

 function sumAndReduce(a, b = []){ var t = 0; if (!a.length) return b; t = a[0] !== a[1] || b[b.length-1] === a[0] ? a.splice(0,1)[0] : a.splice(0,2).reduce((p,c) => p+c); b[b.length-1] === t ? b[b.length-1] += t : b.push(t); return sumAndReduce(a,b); } var myArr = [1, 1, 1, 3, 2, 2, 4, 3], result = sumAndReduce(myArr); console.log(JSON.stringify(result)); console.log(JSON.stringify(sumAndReduce([1, 1, 1, 1]))); console.log(JSON.stringify(sumAndReduce([1, 1, 2, 2]))); 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM