如何填充现有列表/数组 [英] how to populate existing list / array

查看:70
本文介绍了如何填充现有列表/数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是理性/ocaml/函数式编程的新手.

我了解List.append[] @ [],但是这些函数将创建新列表,但是如何填充现有列表/数组?

  1. 填充列表的最佳方法是什么?
  2. 填充数组的最佳方法是什么?表示坐标类型是否为let coords: array point = [];
  3. 还是这种情况下的流程(算法)错误?

原因代码:

type point = {x: int, y: int};

let coords: list point = [];

let append raw =>
  Array.iter
    (
      fun data => {
        let p = {x: data.x, y: data.y};
        /* how to append p to coords */
        ()
      }
    )
    raw;

JS类似物:

const coords = [];
const append = raw => raw.forEach({x, y} => {
  coords.push({
    x: process(x),
    y: process(y)
  });
});

解决方案

欢迎使用推理!

在Reason/OCaml中,列表是不可变的.在后台,它们是简单的单链接列表.每次修改"它们时,您都要创建新的.这是一个示例:

let a = [1, 2, 3];
let b = [0, ...a];

这类似于JavaScript的数组"spread",不同的是这里要使用现有的a,在前面链接一个新节点0,并将其命名为b. a仍指向[1, 2, 3](因此为不变"). b现在是[0, 1, 2, 3].这是有效的,因为[1, 2, 3]部分是共享的.

这样做的好处是,您不必担心传递列表的麻烦,而无需意外地使用晦涩的功能对其进行修改. List的不变性使您可以纯粹通过查看您现在盯着的值来推理代码(因为它永远不会改变!).

list的缺点是在末尾添加内容效率很低:

let c = a @ [4] 

该操作基本上是获取一项[4]的列表,并依次将[1, 2, 3]的每一项附加到该列表.因此,在性能方面呈线性关系.但是从列表实现的简单性来看,从历史上看,这是值得权衡的.

所以3.如果您要设置列表项,那就错了.

  1. 根据您的情况填充列表的最佳方法是通过从旧列表中以非可变方式映射它:let newList = List.map (fun blabla => ...) raw
  2. 与数组相同.映射它.如果您遇到问题,则有Array.of_listArray.to_list.

有关数组的更多信息:OCaml数组是可变的,并且其大小不可更改.将其视为内存块.您可以通过Array.make newSize分配一个新数组,然后通过Array.set进行填充.如果您要大量调整数组的大小,那么这是没有意义的,因此请选择正确的数据结构.

对于JS编译,BuckleScript将ocaml数组编译为JS数组.因此,它是可变的可调整大小的.您将在 Js.Array 下找到熟悉的JS数组操作>

作为一般启发式方法,如果您想更改长度,请尝试filter.如果要更改长度和包含的项目,请尝试fold_left.否则,map.

最近,我们开始实现一些不变的,可调整大小的,可选的可变数组.敬请期待!

I am new at reason / ocaml / functional programming.

I know about List.append and [] @ [] but these functions will create new list but how to populate existing list / array?

  1. What is the best way to populate list?
  2. What is the best way to populate array? Means if coords type is let coords: array point = [];
  3. Or this is wrong flow (algorithm) for such case?

Reason code:

type point = {x: int, y: int};

let coords: list point = [];

let append raw =>
  Array.iter
    (
      fun data => {
        let p = {x: data.x, y: data.y};
        /* how to append p to coords */
        ()
      }
    )
    raw;

JS analogue:

const coords = [];
const append = raw => raw.forEach({x, y} => {
  coords.push({
    x: process(x),
    y: process(y)
  });
});

解决方案

Welcome to Reason!

In Reason/OCaml, lists are immutable. Under the hood they're simple singly-linked list. You create new ones each time you "modify" them. Here's an example:

let a = [1, 2, 3];
let b = [0, ...a];

This is akin to JavaScript's array "spread", except here you're taking the existing a, linking a new node 0 at the front, and calling it b. a still points to [1, 2, 3] (thus "immutable"). b is now [0, 1, 2, 3]. This is efficient since the [1, 2, 3] part is shared.

The advantage of this is that you don't have to worry about passing your list around and accidentally have an obscure function modify it. List's immutability allows you to reason about your code purely by looking at the value you're staring right now (since it'll never change!).

The drawback of list is that it's inefficient to add something at the end:

let c = a @ [4] 

That operation's basically taking a list of one item, [4], and successively attaching each item of [1, 2, 3] to it. So linear in terms of perf. But judging by the simplicity of the list implementation, it was historically deemed worth the tradeoff.

So 3. it's the wrong flow if you're trying to set a list item.

  1. The best way to populate a list in your case is by mapping over it non-mutatively, from the old list: let newList = List.map (fun blabla => ...) raw
  2. Same for array. Map over it. There's Array.of_list and Array.to_list if you're ever stuck.

More on array: OCaml array is mutable, and its size is unchangeable. Think of it as a block of memory. You'd allocate a new array through Array.make newSize, then populate it through Array.set. This wouldn't make sense if you're resizing the array a lot, so choose the right data structure.

For JS compilation, BuckleScript compiles an ocaml array to a JS array. It's thus mutable and resizable. You'll find your familiar JS array operations under Js.Array

As a general heuristic, if you'd like to change the length: try filter. If you'd like to change the length and the contained items, try fold_left. Otherwise, map.

More recently, we've started implementing some immutable, resizable, optionally mutable array. Stay tuned!

这篇关于如何填充现有列表/数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆