Graph 将文件中的所有数据添加到Elixir中的结构中

Graph 将文件中的所有数据添加到Elixir中的结构中,graph,functional-programming,elixir,Graph,Functional Programming,Elixir,我对长生不老药和函数式编程非常陌生 我正在阅读一个描述图形的大型文本文件,需要将其存储在邻接矩阵和/或邻接列表中进行计算 我在试图弄清楚如何保持将值存储在数据结构中时遇到了一个难题,因为数据在函数式编程中是不可变的 该文件如下所示: 3 //Number of Nodes 1 2 //Non-directional edge 3 4 4 2 Q1:如何做到这一点[已解决] Q2:这可以通过流而不是完整文件读取来完成吗?在函数式语言中,您几乎有两种选择: 递归 减少(具体来说,E

我对长生不老药和函数式编程非常陌生

我正在阅读一个描述图形的大型文本文件,需要将其存储在邻接矩阵和/或邻接列表中进行计算

我在试图弄清楚如何保持将值存储在数据结构中时遇到了一个难题,因为数据在函数式编程中是不可变的

该文件如下所示:

3      //Number of Nodes
1 2    //Non-directional edge
3 4
4 2
Q1:如何做到这一点[已解决]


Q2:这可以通过流而不是完整文件读取来完成吗?

在函数式语言中,您几乎有两种选择:

  • 递归
  • 减少(具体来说,
    Enum.reduce
  • 如果您只需要从列表中累积一个值,那么Reduce真的很快很容易

    听起来递归是解决您试图解决的问题的方法:

    File.read!("path/to/file.txt")
    |> String.split("\n", trim: true)
    |> parse(%{})
    
    def parse([line | rest], matrix) do
      add_line_to_matrix(line, matrix)
      parse(rest, matrix)
    end
    

    在函数式语言中,您几乎有两种选择:

  • 递归
  • 减少(具体来说,
    Enum.reduce
  • 如果您只需要从列表中累积一个值,那么Reduce真的很快很容易

    听起来递归是解决您试图解决的问题的方法:

    File.read!("path/to/file.txt")
    |> String.split("\n", trim: true)
    |> parse(%{})
    
    def parse([line | rest], matrix) do
      add_line_to_matrix(line, matrix)
      parse(rest, matrix)
    end
    

    没有一种固定的方法可以将字符串解析为数据结构。对于这样的简单情况,
    String.split
    String.to\u integer
    就足够了。您尚未提供所需的确切输出结构,因此我将演示如何将其解码为整数和边的一对整数列表

    input = "3
    1 2
    3 4
    4 2"
    
    # or input = File.read!("file.txt")
    
    [head | tail] = String.split(input, "\n")
    count = String.to_integer(head)
    edges = for line <- tail do
      [from, to] = String.split(line)
      {String.to_integer(from), String.to_integer(to)}
    end
    
    IO.inspect count
    IO.inspect edges
    

    没有一种固定的方法可以将字符串解析为数据结构。对于这样的简单情况,
    String.split
    String.to\u integer
    就足够了。您尚未提供所需的确切输出结构,因此我将演示如何将其解码为整数和边的一对整数列表

    input = "3
    1 2
    3 4
    4 2"
    
    # or input = File.read!("file.txt")
    
    [head | tail] = String.split(input, "\n")
    count = String.to_integer(head)
    edges = for line <- tail do
      [from, to] = String.split(line)
      {String.to_integer(from), String.to_integer(to)}
    end
    
    IO.inspect count
    IO.inspect edges
    

    另一个带有减速器的示例:

    (1..10)
    |>Enum.to_list#或“file.txt”|>file.read!|>String.split(“\n”)
    |>Enum.reduce(%{},fn i,acc->
    地图,放acc,我
    (完)
    #⇒ %{
    #“a”=>1,
    #“b”=>2,
    #    ...
    #“j”=>10
    #  }
    
    另一个带有减速器的示例:

    (1..10)
    |>Enum.to_list#或“file.txt”|>file.read!|>String.split(“\n”)
    |>Enum.reduce(%{},fn i,acc->
    地图,放acc,我
    (完)
    #⇒ %{
    #“a”=>1,
    #“b”=>2,
    #    ...
    #“j”=>10
    #  }
    
    您也可以给出一个您正在寻找的输出的示例吗?您不需要更新FP中的变量,只需要生成新的变量。减缩器和递归都可能有助于完成这项任务。你能给出一个你正在寻找的输出的例子吗?你不需要更新FP中的变量,你只需要生成新的变量。还原和递归都可能有助于完成这项任务。我想我不能用一个数据流来完成这项任务,是吗?所有的解决方案似乎都是一次获取所有的数据,或者将数据累积起来,然后在上面递归。这不是一个问题,但它让我好奇。我想我不能用一个数据流来完成这个任务,是吗?所有的解决方案似乎都是一次获取所有的数据,或者将数据累积起来,然后在上面递归。这不是问题,但它让我好奇。你创建的地图有问题。只有当每个节点只有一条边时,它才会起作用。代码“%{1=>2,1=>4,1=>3}”将生成一个映射,其中%{1=>3}是唯一的元素,如果将其更改为列表,则可以正常工作。为了让我接受你的回答,你能把“into:%{}”改为“into:[]”和“{String…integer(to)}”改为“[String…integer(to)]”吗?谢谢你指出这一点。我已将输出更改为元组列表。我认为这比列表更惯用。您创建的地图有一个问题。只有当每个节点只有一条边时,它才会起作用。代码“%{1=>2,1=>4,1=>3}”将生成一个映射,其中%{1=>3}是唯一的元素,如果将其更改为列表,则可以正常工作。为了让我接受你的回答,你能把“into:%{}”改为“into:[]”和“{String…integer(to)}”改为“[String…integer(to)]”吗?谢谢你指出这一点。我已将输出更改为元组列表。我认为这比一系列的列表更为惯用。