リストとハッシュ

2015年12月3日

多くのプログラミング環境では、データ構造をリストとハッシュマップの複合体として表現することが一般的になっています。主要な言語のほとんどは、これらのデータ構造の標準バージョンと、それらを操作するための豊富な操作、特にコレクションパイプラインを提供しています。これらのデータ構造は非常に柔軟性が高く、ほとんどの階層構造を処理および操作しやすい方法で表現できます。[1]

このデータ構造の本質は、(通常)2つの複合データ型が存在することです。

  • ハッシュマップは、キーと値のペアからなるデータ構造であり、連想配列、ハッシュテーブル、マップ、または辞書と呼ばれることもあります。
  • リストは単純なシーケンスです。要素の追加または削除に伴って動的にサイズ変更されるため、従来の配列とは少し異なります(ただし、一部の言語では配列と呼ばれています)。整数キーでインデックス付けできます。

ツリーの葉は、他の要素(通常は言語の基本的なプリミティブ(整数や文字列など))でもかまいませんが、リストまたはハッシュとして扱えない他の構造でもかまいません。

ほとんどの場合、アクセス操作が異なるため、リストとハッシュには別々のデータ型があります。しかし、Lisp使いなら誰でもわかるように、ハッシュをキーと値のペアのリストとして表現するのは簡単です。同様に、数値インデックスを持つハッシュをリストとして扱うことができます(Luaのテーブルが行っていることです)。

リストとハッシュの構造は、デフォルトでスキーマレスです。リストには異なる要素を含めることができ、ハッシュには任意のキーの組み合わせを含めることができます。これにより、データ構造は非常に柔軟になりますが、スキーマレスなデータ構造を操作する際には、ほとんど常に暗黙的なスキーマが存在することを覚えておく必要があります。つまり、特定のデータが特定のキーで表現されることを期待しているということです。

リストとハッシュ構造の長所は、存在する実際のキーについて何も知らない汎用操作で操作できることです。これらの操作は、操作するキーでパラメーター化できます。汎用操作は、通常、コレクションパイプラインに配置され、個々の部分を操作することなく、データ構造から必要なものを取り出すための多くのナビゲーション機能を提供します。

通常は柔軟なハッシュをレコードに使用しますが、定義されたレコード構造(またはオブジェクト)を使用する構造を取り、それらのレコード構造が反射操作を提供する場合、ハッシュと同じように操作できます。そのような構造は、入れることができるものを制限しますが(これは多くの場合良いことです)、汎用操作を使用して操作することは非常に役立ちます。ただし、これには、レコードをハッシュのように照会するメカニズムを言語環境が提供する必要があります。

リストとハッシュの構造は、テキスト形式など、簡単にシリアル化できます。JSONはこのようなデータ構造の特に効果的なシリアル化形式であり、私のデフォルトの選択肢です。XMLはリストとハッシュの構造をシリアル化するために使用されることもありますが、それは実用的な仕事はしますが、冗長であり、属性と要素の区別はこれらの構造には意味がありません(テキストのマークアップには十分に意味があります)。

リストとハッシュは非常に一般的であるにもかかわらず、よく考えられたツリー表現を使用したいと思う時があります。そのようなモデルは、より豊富なナビゲーション操作を提供できます。Nokogiriのシリアル化されたXML構造を操作する際に、XPathまたはCSSセレクターを使用してデータ構造をナビゲートできるのは便利です。このような共通のパス指定は、より大きなドキュメントに役立ちます。もう1つの問題は、ツリー内の特定のノードの親または祖先を見つけるのが、本来あるべきよりも面倒になる可能性があることです。Fortran IVでプログラミングを始めたときから、現代の言語で標準装備として豊富なリストとハッシュが存在することは、私のプログラミング人生における明確な改善の1つでしたが、そこで止まる必要はありません。

謝辞

David Johnston、Marzieh Morovatpasand、Peter Gillard-Moss、Philip Duldig、Rebecca Parsons、Ryan Murray、およびSteven Loweは、社内メーリングリストでこの投稿について議論しました。

注記

1: この種のデータ構造に、一般的に受け入れられた言語横断的な用語がないのは不自然だと思います。新語を作りたいと思うのはそのためです。