gpt4 book ai didi

javascript - 如何使用 TypeScript/JavaScript 中的函数式编程将元素推送到 Map 中的数组?

转载 作者:行者123 更新时间:2023-12-05 02:55:55 24 4
gpt4 key购买 nike

我刚刚开始了从 OOP 背景到学习 FP 的旅程,以及从编写普通 TypeScript(命令式?)迁移到函数式 TypeScript 代码的过程。不幸的是,我已经在努力弄清楚如何将其更改为功能代码:

const foos: Map<
string,
Bar[]
> = new Map();

export const addBar = (
key: string,
bar: Bar
) => {
const foo = foos.get(key);

if (foo) {
foo.push(bar);
} else {
foos.set(key, [bar]);
}
};

我了解如何在数组上使用 .map .filter .concat,但如何处理包含数组的 Map?

关于 foos Map,我猜 Map 本身需要是只读的,还有里面的 Bar 数组,所以 .set .push 是不可能的。但是,如果我不能在 Map 上调用 .set 因为它是只读的,那么使用 Map 是否有意义,还是我应该只使用一个对象?

如果没有可变性,如何将元素推送到 Map 值内的数组(或者如果键不存在,则使用数组创建新映射,如上面的代码所示)?

这种性能是否足够,因为我需要每隔几秒向数组添加一个新元素,每次发生更改时复制整个 map (包括它的许多数组)的不可变方式是否会执行得更糟如果我只是像您通常所做的那样改变数组?

最佳答案

您根本无法使用 native Map,因为它仅提供命令式接口(interface)。

您可以使用开源库,例如流行的 ImmutableJS。

或者您可以编写自己的持久(不可变)数据结构。基本要求是您的数据结构提供的操作不会修改输入。相反,每次操作都会返回一个数据结构 -

const PersistentMap =
{ create: () =>
({})
, set: (t = {}, key, value) =>
({ ...t, [key]: value }) // <-- immutable operation
}

我们首先查看 empty 映射,set 操作的结果,然后确保未修改 empty 映射 -

const empty =
PersistentMap.create()

console.log
( empty
, PersistentMap.set(empty, "hello", "world")
, empty
)

// {}
// { hello: "world" }
// {}

现在让我们来看一个新的中间状态,m1。每次我们看到 set 都会返回一个new 持久映射并且不会修改输入 -

const m1 =
PersistentMap.set(empty, "hello", "earth")

console.log
( m1
, PersistentMap.set(m1, "stay", "inside")
, m1
)
// { hello: "earth" }
// { hello: "earth", stay: "inside" }
// { hello: "earth" }

现在回答您的问题,我们可以向我们的 PersitentMap 添加一个 push 操作 - 我们只需要确保不修改输入即可。这是一种可能的实现方式——

const PersistentMap =
{ // ...

, push: (t = {}, key, value) =>
PersistentMap.set // <-- immutable operation
( t
, key
, Array.isArray(t[key])
? [ ...t[key], value ] // <-- immutable operation
: [ value ]
)
}

我们在下面看到了 push 的 Action 。请注意,m2empty 都不会因此更改 -

const m2 =
PersistentMap.push(empty, "fruits", "apple")

console.log
( m2
, PersistentMap.push(m2, "fruits", "peach")
, m2
, empty
)

// { fruits: [ "apple" ] }
// { fruits: [ "apple", "peach" ] }
// { fruits: [ "apple" ] }
// {}

展开下面的代码片段以在您自己的浏览器中验证结果

const PersistentMap =
{ create: () =>
({})
, set: (t = {}, key, value) =>
({ ...t, [key]: value })
, push: (t = {}, key, value) =>
PersistentMap.set
( t
, key
, Array.isArray(t[key])
? [ ...t[key], value ]
: [ value ]
)
}

const empty =
PersistentMap.create()

console.log
( empty
, PersistentMap.set(empty, "hello", "world")
, empty
)
// {}
// { hello: "world" }
// {}

const m1 =
PersistentMap.set(empty, "hello", "earth")

console.log
( m1
, PersistentMap.set(m1, "stay", "inside")
, m1
)
// { hello: "earth" }
// { hello: "earth", stay: "inside" }
// { hello: "earth" }

const m2 =
PersistentMap.push(empty, "fruits", "apple")

console.log
( m2
, PersistentMap.push(m2, "fruits", "peach")
, m2
, empty
)
// { fruits: [ "apple" ] }
// { fruits: [ "apple", "peach" ] }
// { fruits: [ "apple" ] }
// {}

关于javascript - 如何使用 TypeScript/JavaScript 中的函数式编程将元素推送到 Map 中的数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60960603/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com