[英]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的數組函數map
或reduce
演示這一點,那就太好了。
沒有任何遞歸就可能嗎?
有人提到了它的可能,那么如果不使用遞歸的話我會很好
在此處添加此內容是因為有些人已經提供了答案。
如果是:
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.