У меня есть одномерный массив строк (Array {String, 1}), который описывает матрицу чисел с плавающей запятой (см. Ниже). Мне нужно разобрать эту матрицу. Есть какие-нибудь приятные предложения?

  • Юля 1.5
  • MacOS

Да, я прочитал это из файла. Я не хочу читать все это при использовании CSV, потому что я хочу сохранить возможность чтения всего файла с использованием ввода-вывода памяти, чего я не думаю, что CSV есть. Кроме того, у меня есть несколько сложных строк, включая строки и числа, а также строки и строки, которые мне нужно проанализировать, что исключает DelimitedFiles. Столбцы разделены двумя пробелами.

julia> lines[24+member_total:idx-1]
49-element Array{String,1}:
 "0.0000000E+00  0.0000000E+00  0.0000000E+00  1.3308000E+01"
 "0.0000000E+00  0.0000000E+00  1.9987500E-01  1.3308000E+01"
 "0.0000000E+00  0.0000000E+00  1.1998650E+00  1.3308000E+01"
 "0.0000000E+00  0.0000000E+00  2.1998550E+00  1.3308000E+01"
 "0.0000000E+00  0.0000000E+00  3.1998450E+00  1.3308000E+01"
 "0.0000000E+00  0.0000000E+00  4.1998350E+00  1.3308000E+01"
 ⋮
 "0.0000000E+00  0.0000000E+00  5.9699895E+01  1.4000000E-01"
 "0.0000000E+00  0.0000000E+00  6.0199890E+01  1.0100000E-01"
 "0.0000000E+00  0.0000000E+00  6.0699885E+01  6.2000000E-02"
 "0.0000000E+00  0.0000000E+00  6.1199880E+01  2.3000000E-02"
 "0.0000000E+00  0.0000000E+00  6.1500000E+01  0.0000000E+00"
3
cardoza2 12 Ноя 2020 в 20:01

3 ответа

Лучший ответ

Я категорически против изобретения велосипеда и использования индивидуальных синтаксических анализаторов из-за практической надежности таких решений в производстве.

Если ваш файл используется для однократного использования String:

using DelimitedFiles
readdlm(IOBuffer(strs))

Если ваш файл как Vector из String использует

cat(readdlm.(IOBuffer.(strsa))...,dims=1)

Наконец, нет конфликта в использовании карт памяти вместе с CSV:

using Mmap

s = open("d.txt") # d.txt contains your lines
                  # if you want to read & wrtie use "w+" option
 
m = Mmap.mmap(s, Vector{UInt8}) # memory mapping of your file

readdlm(IOBuffer(m))

При этом вы всегда можете установить поток в начало и читать данные независимо от карты памяти:

seek(s,0)
readdlm(s)
seek(s,0) # reset the stream
4
Przemyslaw Szufel 12 Ноя 2020 в 19:14

Я обошелся. Не самое приятное, но работает ...

function rmspaces(line)
    line = replace(line, "\t" => " ")
    # println("line: ", line)
    while occursin("  ", line)
        line = replace(line, "  "=>" ")
        # println("line: ", line)
    end

    return line
end

function readmatrix(lines, numcolumns::Int64; type=Float64)
    #Remove the spaces to one
    for i=1:length(lines)
        lines[i] = rmspaces(lines[i])
    end

    matrix = zeros(length(lines), numcolumns)

    for i=1:length(lines)
        idx = 1 # set the initial stop at the beginning
        spot = 1
        for j=1:length(lines[i])
            if lines[i][j]==' ' && j>1 #Stops at spaces
                number = parse(type,lines[i][idx:j]) #from the last stop to this one
                idx = j #Set this stop in memory
                matrix[i,spot] = number
                spot += 1
            end
        end
        if spot<numcolumns+1 #If there isn't a space after the last number,
            #we need to attach the last number in every row. If the last number
            #was appended, then the spot will be increased to be more than the number
            #of columns.
            number = parse(type, lines[i][idx:end])
            matrix[i,spot] = number
        end
    end
    return matrix
end
1
cardoza2 12 Ноя 2020 в 17:33
strs = ["0.0000000E+00  0.0000000E+00  0.0000000E+00  1.3308000E+01",
        "0.0000000E+00  0.0000000E+00  1.9987500E-01  1.3308000E+01",
        "0.0000000E+00  0.0000000E+00  1.1998650E+00  1.3308000E+01"]

mapreduce(vcat, strs) do s
    (parse.(Float64, split(s, "  ")))'
end
3×4 Array{Float64,2}:
 0.0  0.0  0.0       13.308
 0.0  0.0  0.199875  13.308
 0.0  0.0  1.19986   13.308
2
Cameron Bieganek 12 Ноя 2020 в 18:23