假如說
m是Map<number, V>某種型別的Vk是一個number,
我如何寫下一個運算式
- 要么得到一個已經存在
V的密鑰k,要么 - 創建一個新的
v: V,將其放入鍵的映射中k,然后計算為v?
例如,如果它已經存在則SOME_EXPR(m, k, [])應該回傳,或者放入并回傳.m.get(k)[]m.set(k, [])[]
具體例子
假設我想逐步構建一個Map<number, number[]>. 我想將值100和分配200給鍵48,并將值分配300給52。我想在需要時按需創建新的空陣列。為此,我需要類似這樣的SOME_EXPR(map, key, value)東西
var m = new Map(); // Map<number, number[]>
SOME_EXPR(m, 48, []).push(100)
SOME_EXPR(m, 48, []).push(200)
SOME_EXPR(m, 52, []).push(300)
結果是一張地圖
{ 48 -> [100, 200]; 52 -> [300] }
應該寫什么而不是SOME_EXPR?
我試過的
當然,我可以創建一個輔助方法:
function getOrElseUpdate(m, k, defaultValue) {
if (!m.has(k)) {
m.set(k, defaultValue);
}
return m.get(k);
}
然后使用SOME_EXPR(m, k, []) := getOrElseUpdate(m, k, []). 但它不僅要計算三次哈希碼,而且重量級和煩人(對于代碼的維護者來說可能并不明顯,他們必須單擊它才能查看另一個檔案中的定義等)。
我可以嘗試以某種方式行內它:
SOME_EXPR(m,k,v) := ((k) => (m.get(k) || ((v) => (m.set(k, v), v))(v)))(k)
這樣上面的例子就會變成
var m = new Map();
((k) => (m.get(k) || ((v) => (m.set(k, v), v))([])))(42).push(100);
((k) => (m.get(k) || ((v) => (m.set(k, v), v))([])))(42).push(200);
((k) => (m.get(k) || ((v) => (m.set(k, v), v))([])))(58).push(300);
這有效,但很奇怪。
我也嘗試過四處尋找相關的答案,但這個搜索結果令人沮喪地沒有結果。
有沒有慣用的方法來實作這一目標?(最好也可以在 TS 中很好地鍵入)
其他一些語言的類似方法
(可選;如果您不使用 JVM,請跳過此步驟)
在 Scala 中,它看起來有點像這樣:
val m = HashMap.empty[Int, ListBuffer[Int]]
m.getOrElseUpdate(48, ListBuffer.empty) = 100
m.getOrElseUpdate(48, ListBuffer.empty) = 200
m.getOrElseUpdate(52, ListBuffer.empty) = 300
// m is now:
//
// HashMap(
// 48 -> ListBuffer(100, 200),
// 52 -> ListBuffer(300)
// )
在 Java 中,非常相似:
HashMap<Integer, List<Integer>> m = new HashMap<>();
m.computeIfAbsent(42, k -> new LinkedList<>()).add(100);
m.computeIfAbsent(42, k -> new LinkedList<>()).add(200);
m.computeIfAbsent(58, k -> new LinkedList<>()).add(300);
// m = {58=[300], 42=[100, 200]}
uj5u.com熱心網友回復:
我嘗試了很多選項,但如果您只是在尋找可讀性,我個人認為這是最好的選擇,我可能錯了,希望看到更優雅的東西;
var m = new Map();
function SOME_EXPR(m, k, v) {
return m.get(k) || (m.set(k, v) && v);
}
function add(m, k, v) {
SOME_EXPR(m, k, []).push(v)
}
add(m, 48, 100)
add(m, 48, 200)
add(m, 52, 300)
console.log(m);
uj5u.com熱心網友回復:
我嘗試將您的慣用示例代碼打低一點:
((k, d) => m.get(k) ?? (m.set(k, d), d))(48, []).push(100);
我實際上認為呼叫類似的函式getOrElseUpdate可以幫助作為檔案。如果維護者偶然發現它,他/她可能知道 Scala 并且知道它應該做什么。
uj5u.com熱心網友回復:
可能沒有太大的改進和傳播運算子的缺點,但是你怎么看?
function addValue(m, k, v) {
m.set(k, [...(m.get(k) || []), v]);
}
var map = new Map();
addValue(map, 48, 100);
addValue(map, 48, 200);
addValue(map, 52, 300);
console.log(map);
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/530722.html
上一篇:如何正確組合這兩個查詢?
