Split the CSV string into variables based on the table header

Hello everyone) Please advise, is there any simple ready-made solution for my issue?

I need the variables in a partial template to correspond to the column names in a CSV table.
Currently, I have to create a separate variable for each column, but if there are 20-30 of them, it seems like too many.

Here is my CSV file for example:

place;name;money
1;macdonalds;10000
2;kfc;7000
3;burgerking;3000

Here is my template in index.html

{{ $data := dict }}
{{ $p := "/top.csv" }}
{{  with .Resources.GetMatch  $p }}
  {{ $opts := dict "delimiter" ";" }}
  {{ $data = . | transform.Unmarshal $opts }}
{{ else }}
  {{ errorf "Unable to get resource %q" $p }}
{{ end }}


{{/*  skip first line  */}}
{{ range after 1 $data }}
{{ with partial "top.html" . }}
            {{ . }}
            {{ end }}
          {{ end }}

And this is how variables are currently declared in top.html:

{{$place := index . 0 }}
{{$name := index . 1 }}
{{$money := index . 2 }}

<div>
   Place is: {{$place}}
</div>

<div>
  Name is:  {{$name}}
</div>

<div>
   Money:  {{$money}}
</div>

Everything seems to be working fine, but I wanted to know if there is a more elegant solution. Thank you in advance.

I think the most likely approach is to iterate over the first row of the CSV and assign the values of each column to variables. Then, further assign values to each variable. However, neither myself nor my little friend GPT seem to be able to figure this out :slight_smile:

I would convert the CSV data to a slice of maps, then access the values via their key names.

layouts/_default/single.html
{{ $data := dict }}
{{ $p := "top.csv" }}
{{ with .Resources.GetMatch $p }}
  {{ $opts := dict "delimiter" ";" }}
  {{ with . | transform.Unmarshal $opts }}
    {{ $data = partial "csv-to-map.html" . }}
  {{ end }}
{{ else }}
  {{ errorf "Unable to get resource %q" $p }}
{{ end }}

{{ range $data }}
  <div>
    Place is: {{ .place }}
  </div>
  <div>
    Name is: {{ .name }}
  </div>
  <div>
    Money: {{ .money }}
  </div>
{{ end }}
layouts/partials/csv-to-map.html
{{ $headerRow := index . 0 }}
{{ $s := slice }}
{{ range . | after 1 }}
  {{ $m := dict }}
  {{ range $k, $v := . }}
    {{ $m = merge $m (dict (index $headerRow $k) $v) }}
  {{ end }}
  {{ $s = $s | append $m }}
{{ end }}
{{ return $s }}

Try it:

git clone --single-branch -b hugo-forum-topic-50473 https://github.com/jmooring/hugo-testing hugo-forum-topic-50473
cd hugo-forum-topic-50473
hugo server
1 Like

Thank you very much, it works perfectly and thanks for the separate git, when I inserted the code myself, why did the first column skip, because with your code in git everything is perfect. Thanks a lot for your help and time!

I have no way of knowing without seeing your code and CSV file.

I think maybe the problem was in the CSV file itself, anyway, now everything works, thank you!

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.