这里有几种不同的方法来做到这一点。如果你想坚持Js.Array
你在评论中提到的,你可以这样做:
type point = {
x: int,
y: int,
};
let points: array(point) = [|{x: 2, y: 4}|];
let rawArray = [|[|1, 2|], [|3, 4|], [|9, 4|]|];
let append = raw => {
Array.iter(
a => {
let data: point = {x: a[0], y: a[1]};
Js.Array.push(data, points)->ignore;
},
raw,
);
};
append(rawArray);
Js.log2("new points", points);
...or with tuples with `Js.Array`
let rawTuples = [|(3, 5), (4, 9), (9, 4)|];
append(rawTuples);
Js.log2("new points", points);
[ { x: 2, y: 4 }, { x: 3, y: 5 }, { x: 4, y: 9 }, { x: 9, y: 4 } ]
如果您想按照@chenglou 的建议进行操作,您可以尝试Array.fold_left
使用Array.append
rawArray|>Array.fold_left((a, b) =>
Array.append(a, [|{x: b[0], y: b[1]}|]), [||]);
使用一些辅助功能可能会更清洁,例如:
let concatMap = f =>
Array.fold_left((a, b) => Array.append(a, f(b)), [||]);
let newPoint = coord => [|{x: coord[0], y: coord[1]}|];
然后调用:
let rawTuples = [|(3, 5), (4, 9), (9, 4)|];
let arrayTuples = rawTuples |> concatMap(a => [|{x: fst(a), y: snd(a)}|]);
使用 helpers 也有助于我理解函数的每个部分在做什么。
也可以使用,tuples
因为这些只是 ReasonML/Ocaml/Rescript 中的数组
let rawTuples = [|(3, 5), (4, 9), (9, 4)|];
let arrayTuples = rawTuples |> concatMap(a => [|{x: fst(a), y: snd(a)}|]);
您可以选择使用mutable records
.
这就是更新可变记录数组的内容。它没有太大的不同。
这里我们使用一个函数来改变数组中的数据。
let printCoords = coords => Array.iter(Js.log, coords);
type mutablePoint('a, 'b) = {
mutable x: 'a,
mutable y: 'b,
};
let data1: mutablePoint(int, int) = {x: 2, y: 4};
let data2: mutablePoint(int, int) = {x: 3, y: 4};
let data3: mutablePoint(int, int) = {x: 4, y: 4};
let isEven = n => {
n mod 2 == 0;
};
let multiplyByY = data => data.x = data.x * data.y;
let makeItOdd = data => data.x = data.x + 1;
let updateData = data => data.x->isEven
? data->makeItOdd : multiplyByY(data);
let points: array(mutablePoint('x, 'y)) = [|data1, data2, data3|];
let append = (fn, data) => {
Array.iter(x => {fn(x)}, data);
data;
};
points |> append(updateData);
Js.log("points after");
printCoords(points);
// points after { x: 3, y: 4 } { x: 12, y: 4 }{ x: 5, y: 4 }
您的问题是关于从一些原始数据进行更新,所以这里是一个示例,我们在索引 i 处获取原始数据并使用它来更改x
可变数组上的值:
let points2: array(mutablePoint('x, 'y)) = [|data1, data2, data3|];
let printCoords = coords => Array.iter(Js.log, coords);
printCoords(points2);
let rawData = [|[|1, 2|], [|3, 4|], [|9, 4|]|];
let update_x_on_point_i = (i, x) => points2[i].x = x;
let append = raw =>
Array.iteri(
(i, d) => {
let x: int = d[0];
update_x_on_point_i(i, x);
},
raw,
);
append(rawData);
Js.log2("points2 after: ", points2);
printCoords(points2);
// points2 after: [ { x: 1, y: 4 }, { x: 3, y: 4 }, { x: 9, y: 4 } ]
这两个数组恰好是相同的大小,所以没有例外,但是一旦数组长度不同,很容易有一个,所以我们应该在现实生活中处理它。
只是因为我今天碰巧这样做了,原因与我写这篇文章的原因相同,这里是JS Analogue
版本。
type point = {
x: int,
y: int,
};
let coords = [|{x: 9, y: 7}, {x: 2, y: 4}, {x: 3, y: 8}|];
Js.log("coords before");
Js.log("-------");
let append = raw =>
raw->Belt.Array.mapWithIndex(
_,
(i, r) => {
let new_point_i = {x: r[0], y: r[1]};
coords[i] = new_point_i;
},
);
let rawData = [|[|1, 2|], [|3, 4|], [|9, 4|]|];
append(rawData);
Js.log("coords after");
Js.log(coords);
coords before
[ { x: 9, y: 7 }, { x: 2, y: 4 }, { x: 3, y: 8 } ]
-------
coords after
[ { x: 1, y: 2 }, { x: 3, y: 4 }, { x: 9, y: 4 } ]
更新
以下代码是上面注释中的要点中@yawar 代码的更新语法。他的解释值得一读。
type data_item = {
symbol: string,
next: bool,
};
/* Convenience function for making data items. */
let make_data_item = (symbol, next) => {symbol, next};
let process = (data: list(data_item)) => {
/*
We track the current symbol as well as the result list in the folding function.
*/
let fold_func = ((current, result), {symbol, next}) =>
if (next) {
(symbol, [current, ...result]);
} else {
(current ++ symbol, result);
};
let (current, result) = List.fold_left(fold_func, ("", []), data);
/*
We need to reverse the result list because `[el, ...els]` above actually
builds it up in the _opposite_ order to the original input list.
*/
(current, List.rev(result));
};
let result =
process([
make_data_item("a", false),
make_data_item("b", false),
make_data_item("c", true),
make_data_item("d", false),
]);
/* result = ("cd", ["ab"]) */