How should Erlang filter the elements in the list, and add punctuation and []?

265 views Asked by At
-module(solarSystem).

-export([process_csv/1, is_numeric/1, parseALine/2, parse/1, expandT/1, expandT/2,
         parseNames/1]).

parseALine(false, T) ->
    T;
parseALine(true, T) ->
    T.

parse([Name, Colour, Distance, Angle, AngleVelocity, Radius, "1" | T]) ->
    T;%Where T is a list of names of other objects in the solar system
parse([Name, Colour, Distance, Angle, AngleVelocity, Radius | T]) ->
    T.

parseNames([H | T]) ->
    H.

expandT(T) ->
    T.

expandT([], Sep) ->
    [];
expandT([H | T], Sep) ->
    T.

% https://rosettacode.org/wiki/Determine_if_a_string_is_numeric#Erlang
is_numeric(L) ->
    S = trim(L, ""),
    Float = (catch erlang:list_to_float(S)),
    Int = (catch erlang:list_to_integer(S)),
    is_number(Float) orelse is_number(Int).

trim(A) ->
    A.

trim([], A) ->
    A;
trim([32 | T], A) ->
    trim(T, A);
trim([H | T], A) ->
    trim(T, A ++ [H]).

process_csv(L) ->
    X = parse(L),
    expandT(X).

The problem is that it will calls process_csv/1 function in my module in a main, L will be a file like this:

[["name "," col"," dist"," a"," angv"," r "," ..."],["apollo11 ","white"," 0.1"," 0"," 77760"," 0.15"]]

Or like this:

["planets ","earth","venus "]

Or like this:

["a","b"]

I need to display it as follows:

apollo11 =["white", 0.1, 0, 77760, 0.15,[]];
Planets =[earth,venus]
a,b
[[59],[97],[44],[98]]

My problem is that no matter how I make changes, it can only show a part, and there are no symbols. The list cannot be divided, so I can't find a way. In addition, because Erlang is a niche programming language, I can't even find examples online. So, can anyone help me? Thank you, very much. In addition, I am restricted from using recursion.

1

There are 1 answers

0
Agus On

I think the first problem is that it is hard to link what you are trying to achieve with what your code says thus far. Therefore, this feedback maybe is not exactly what you are looking for, but might give some ideas.
Let's structure the problem into the common elements: (1) input, (2) process, and (3) output.

  1. Input
    You mentioned that L will be a file, but I assume it is a line in a file, where each line can be one of the 3 (three) samples. In this regard, the samples also do not have consistent pattern.
    For this, we can build a function to convert each line of the file into Erlang term and pass the result to the next step.

  2. Process
    The question also do not mention the specific logic in parsing/processing the input. You also seem to care about the data type so we will convert and display the result accordingly. Erlang as a functional language will naturally be handling list, so on most cases we will need to use functions on lists module

  3. Output
    You didn't specifically mention where you want to display the result (an output file, screen/erlang shell, etc), so let's assume you just want to display it in the standard output/erlang shell.

    Sample file content test1.txt (please note the dot at the end of each line)

[["name "," col"," dist"," a"," angv"," r "],["apollo11 ","white","0.1"," 0"," 77760"," 0.15"]].
["planets ","earth","venus "].
["a","b"].

Howto run: solarSystem:process_file("/Users/macbook/Documents/test1.txt").
Sample Result:

(dev01@Macbooks-MacBook-Pro-3)3> solarSystem:process_file("/Users/macbook/Documents/test1.txt").
apollo11 = ["white",0.1,0,77760,0.15] 
planets = ["earth","venus"] 
a = ["b"] 
Done processing 3 line(s) 
ok

Module code:


-module(solarSystem). 

-export([process_file/1]).
-export([process_line/2]).
-export([format_item/1]).

%%This is the main function, input is file full path
%%Howto call: solarSystem:process_file("file_full_path").
process_file(Filename) ->
    %%Use file:consult to convert the file content into erlang terms
    %%File content is a dot (".") separated line
    {StatusOpen, Result} = file:consult(Filename),
    case StatusOpen of
        ok ->
                %%Result is a list and therefore each element must be handled using lists function
                Ctr = lists:foldl(fun process_line/2, 0, Result),
                io:format("Done processing ~p line(s) ~n", [Ctr]);
         _ ->   %%This is for the case where file not available
                io:format("Error converting file ~p due to '~p' ~n", [Filename, Result])
    end.

process_line(Term, CtrIn) ->
    %%Assume there are few possibilities of element. There are so many ways to process the data as long as the input pattern is clear.
    %%We basically need to identify all possibilities and handle them accordingly.
    %%Of course there are smarter (dynamic) ways to handle them, but below may give you some ideas.
    case Term of
        %%1. This is to handle this pattern -> [["name "," col"," dist"," a"," angv"," r "],["apollo11 ","white"," 0.1"," 0"," 77760"," 0.15"]]
        [[_, _, _, _, _, _], [Name | OtherParams]] ->
                                                        %%At this point, Name = "apollo11", OtherParamsList = ["white"," 0.1"," 0"," 77760"," 0.15"]
                                                        OtherParamsFmt = lists:map(fun format_item/1, OtherParams),
                                                        %%Display the result to standard output
                                                        io:format("~s = ~p ~n", [string:trim(Name), OtherParamsFmt]);
        %%2. This is to handle this pattern -> ["planets ","earth","venus "]
                             [Name | OtherParams] ->
                                                        %%At this point, Name = "planets ", OtherParamsList = ["earth","venus "]
                                                        OtherParamsFmt = lists:map(fun format_item/1, OtherParams),
                                                        %%Display the result to standard output
                                                        io:format("~s = ~p ~n", [string:trim(Name), OtherParamsFmt]); 
        %%3. Other cases
                                                    _ ->
                                                        %%Display the warning to standard output
                                                        io:format("Unknown pattern ~p ~n", [Term])
    end,
    CtrIn + 1.
    
%%This is to format the string accordingly
format_item(Str) ->
    StrTrim = string:trim(Str), %%first, trim it
    format_as_needed(StrTrim).

format_as_needed(Str) ->
    Float = (catch erlang:list_to_float(Str)),
    case Float of
        {'EXIT', _} ->  %%It is not a float -> check if it is an integer
                        Int = (catch erlang:list_to_integer(Str)),
                        case Int of
                            {'EXIT', _} ->  %%It is not an integer -> return as is (string)
                                            Str;
                                    _  ->   %%It is an int
                                            Int
                        end;
                _  ->   %%It is a float
                        Float
    end.