リートン で elixir を学ぶ （その4）text ファイルの update

こちらと同様のことを [wrtn](wrtn.jp) で行いました。
[ChatGPT で elixir を学ぶ　（その6）text ファイルの update](https://qiita.com/ekzemplaro/items/c88e20888bc426571e02)

リートンでは、Map の更新のスニペットを作成しました。(Python と同等の機能のプログラムは作成できませんでした。）

## Python のプログラム

```py:text_update.py
#! /usr/bin/python
#
#	update/text_update.py
#
#					Mar/07/2024
import	sys
import	datetime
#
# ---------------------------------------------------------------
def dict_update_proc(dict_in,id,population):
	key = str(id)
	if key in dict_in:
		dict_in[key]['population'] = population
		date_mod = datetime.date.today()
		dict_in[key]['date_mod'] = '%s' % date_mod
#
	return	dict_in
#
# ---------------------------------------------------------------
def text_write_proc(file_out,dict_aa):
#
	fp_out = open(file_out,mode='w', encoding='utf-8')
	for key in dict_aa.keys():
		unit = dict_aa[key]
		str_out = key + "\t" + str(unit['name']) + "\t"
		str_out += "%d\t" % unit['population']
		str_out += unit['date_mod'] + "\n"
		fp_out.write(str_out)
	fp_out.close()
# ---------------------------------------------------------------
def text_read_proc(file_in):
#
	fp_in = open(file_in,encoding='utf-8')
	lines = fp_in.readlines()
	fp_in.close()
#
	dict_aa = {}
	for line in lines:
		if (5 < len(line)):
			cols= line[:-1].split('\t')
			if (3 < len(cols)):
				try:
					if (cols[0][0] == "t"):
						dict_unit = {'name': cols[1], \
			'population':int (cols[2]),'date_mod':cols[3]}
						dict_aa[cols[0]] = dict_unit
				except:
					sys.stderr.write \
				("*** error *** %s ***\n" % file_in)
					sys.stderr.write \
				("*** %s ***\n" % line)
#
	return	dict_aa
# ---------------------------------------------------------------
#
sys.stderr.write("*** 開始 ***\n")
#
file_in = sys.argv[1]
id_in = sys.argv[2]
population_in = int(sys.argv[3])
print("%s\t%d" % (id_in, population_in))

dict_aa = text_read_proc(file_in)

dict_bb=dict_update_proc(dict_aa,id_in,population_in)

text_write_proc(file_in,dict_bb)
#
sys.stderr.write("*** 終了 ***\n")
# ---------------------------------------------------------------
```

## リートンで得たプログラム

```elixir
def update_dict(dict, id, population) do
  date_mod = Date.utc_today()
  Map.update!(dict, id, fn _ -> %{population: population, date_mod: date_mod} end)
end
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/94f91a8f-fc28-9b2b-d2ed-540ab429f636.png)

これだと、name が欠落するので、次のように修正しました。

```elixir
defmodule TextUpdate do
def update_dict(dict, id, population) do
  date_mod = Date.utc_today()
  name = dict[id].name
  IO.puts name
#  Map.update!(dict, id, fn _ -> %{population: population, date_mod: date_mod} end)
  Map.update!(dict, id, fn _ -> %{population: population, name: name, date_mod: "#{date_mod}"} end)
end
```

こちらの読み込みプログラム
[リートン で elixir を学ぶ （その3）text ファイルの read](https://qiita.com/ekzemplaro/items/b5e4fbccbdcc7b387a84)
こちらの書き込みプログラム
[リートン で elixir を学ぶ （その2）text ファイルの write](https://qiita.com/ekzemplaro/items/3ad1a9b6722ba0f6faa2)
を使って、次のプログラムを作成しました。

```elixir:text_update.exs
#! /usr/bin/elixir

defmodule TextUpdate do
def update_dict(dict, id, population) do
  date_mod = Date.utc_today()
  name = dict[id].name
  IO.puts name
#  Map.update!(dict, id, fn _ -> %{population: population, date_mod: date_mod} end)
  Map.update!(dict, id, fn _ -> %{population: population, name: name, date_mod: "#{date_mod}"} end)
end

  def text_write_proc(file_out, dict_aa) do
    {:ok, file} = File.open(file_out, [:write, :utf8])

    dict_aa
    |> Enum.each(fn {key, val} ->
      str_out = "#{key}\t#{val.name}\t#{val.population}\t#{val.date_mod}\n"
      IO.write(file, str_out)
    end)

    File.close(file)
  end


  def read_file(file_path) do
    file_path
    |> File.stream!()
    |> Enum.reduce(%{}, fn line, acc ->
      process_line(line, acc)
    end)
  end

  defp process_line(line, acc) do
    [key, name, population, date_mod | _] = String.split(line, "\t")
    if String.starts_with?(key, "t") do
      Map.put(acc, key, %{
        name: name,
        population: String.to_integer(population),
#        date_mod: date_mod
        date_mod: String.trim_trailing(date_mod)
      })
    else
      acc
    end
  end

end
#
IO.puts :stderr,"*** 開始 ***"
[file_in, id_in, population_in_str]  = System.argv()
IO.puts :stderr,file_in

population_in = String.to_integer(population_in_str)

# IO.puts("#{id_in}\t#{population_in}")

dict_aa = TextUpdate.read_file(file_in)

# IO.inspect(dict_aa)

dict_bb = TextUpdate.update_dict(dict_aa, id_in, population_in)


IO.inspect(dict_bb)

TextUpdate.text_write_proc(file_in, dict_bb)


IO.puts :stderr,"*** 終了 ***"
```

実行結果

```text
$ ./text_update.exs cities.txt t2382 79534100
*** 開始 ***
cities.txt
t2382	79534100
豊橋
*** 終了 ***
```