6

オブジェクト (Python/Ruby/Java/C#) からテーブルを生成する方法はありますか?

プログラムで簡単なテーブルを作成したいと思います。いくつかのオブジェクトがあり、いくつかのプロパティをヘッダーに、コレクションを行にマップしたいと考えています。

なぜマークダウン?その文書を後で手動で編集したいからです。現在、プロセス全体は次のようになっています。

  • レポーティング エンジンは C# です
  • DOCX が生成されるオブジェクトがあります (中間 XML などがあります)。
  • ほとんどの場合、マイナーな修正を行う必要があり、その docx ドキュメントを MS Word で開く必要があります。
  • 開発者チームにすべてのバグを修正するように依頼するのは面倒です。なぜなら、彼らにはすぐに修正する時間がなく、次のリリースを待たなければならないからです。

Markdown ドキュメントを取得すると、簡単に編集し、いくつかの変数を挿入し、pandoc を使用してそれらの変数を特定のデータに置き換えることができることがわかりました。しかし、Markdown を取得するには、開発者が Markdown でテーブルを生成する方法を知る必要があります。

4

3 に答える 3

12

Doxygen Markdown テーブルを生成するには、ほぼ同じことを行う必要があったので、共有したいと思いました。サンプル コードは Python 2.7 と 3.3 の両方で正常に実行されましたが、厳密にテストしたとは言えません。

# Generates tables for Doxygen flavored Markdown.  See the Doxygen
# documentation for details:
#   http://www.doxygen.nl/manual/markdown.html#md_tables

# Translation dictionaries for table alignment
left_rule = {'<': ':', '^': ':', '>': '-'}
right_rule = {'<': '-', '^': ':', '>': ':'}

def evalute_field(record, field_spec):
    """
    Evalute a field of a record using the type of the field_spec as a guide.
    """
    if type(field_spec) is int:
        return str(record[field_spec])
    elif type(field_spec) is str:
        return str(getattr(record, field_spec))
    else:
        return str(field_spec(record))

def table(file, records, fields, headings, alignment = None):
    """
    Generate a Doxygen-flavor Markdown table from records.

    file -- Any object with a 'write' method that takes a single string
        parameter.
    records -- Iterable.  Rows will be generated from this.
    fields -- List of fields for each row.  Each entry may be an integer,
        string or a function.  If the entry is an integer, it is assumed to be
        an index of each record.  If the entry is a string, it is assumed to be
        a field of each record.  If the entry is a function, it is called with
        the record and its return value is taken as the value of the field.
    headings -- List of column headings.
    alignment - List of pairs alignment characters.  The first of the pair
        specifies the alignment of the header, (Doxygen won't respect this, but
        it might look good, the second specifies the alignment of the cells in
        the column.

        Possible alignment characters are:
            '<' = Left align (default for cells)
            '>' = Right align
            '^' = Center (default for column headings)
    """

    num_columns = len(fields)
    assert len(headings) == num_columns

    # Compute the table cell data
    columns = [[] for i in range(num_columns)]
    for record in records:
        for i, field in enumerate(fields):
            columns[i].append(evalute_field(record, field))

    # Fill out any missing alignment characters.
    extended_align = alignment if alignment != None else []
    if len(extended_align) > num_columns:
        extended_align = extended_align[0:num_columns]
    elif len(extended_align) < num_columns:
        extended_align += [('^', '<')
                           for i in range[num_columns-len(extended_align)]]

    heading_align, cell_align = [x for x in zip(*extended_align)]

    field_widths = [len(max(column, key=len)) if len(column) > 0 else 0
                    for column in columns]
    heading_widths = [max(len(head), 2) for head in headings]
    column_widths = [max(x) for x in zip(field_widths, heading_widths)]

    _ = ' | '.join(['{:' + a + str(w) + '}'
                    for a, w in zip(heading_align, column_widths)])
    heading_template = '| ' + _ + ' |'
    _ = ' | '.join(['{:' + a + str(w) + '}'
                    for a, w in zip(cell_align, column_widths)])
    row_template = '| ' + _ + ' |'

    _ = ' | '.join([left_rule[a] + '-'*(w-2) + right_rule[a]
                    for a, w in zip(cell_align, column_widths)])
    ruling = '| ' + _ + ' |'

    file.write(heading_template.format(*headings).rstrip() + '\n')
    file.write(ruling.rstrip() + '\n')
    for row in zip(*columns):
        file.write(row_template.format(*row).rstrip() + '\n')

簡単なテストケースを次に示します。

import sys

sys.stdout.write('State Capitals (source: Wikipedia)\n\n')

headings = ['State', 'Abrev.', 'Capital', 'Capital since', 'Population',
            'Largest Population?']

data = [('Alabama', 'AL', '1819', 'Montgomery', '1846', 155.4, False,
         205764),
        ('Alaska', 'AK', '1959', 'Juneau', '1906', 2716.7, False, 31275),
        ('Arizona', 'AZ', '1912', 'Phoenix', '1889',474.9, True, 1445632),
        ('Arkansas', 'AR', '1836', 'Little Rock', '1821', 116.2, True,
         193524)]

fields = [0, 1, 3, 4, 7, lambda rec: 'Yes' if rec[6] else 'No']

align = [('^', '<'), ('^', '^'), ('^', '<'), ('^', '^'), ('^', '>'),
         ('^','^')]

table(sys.stdout, data, fields, headings, align)

次の出力が得られます。

State Capitals (source: Wikipedia)

|  State   | Abrev. |   Capital   | Capital since | Population | Largest Population? |
| :------- | :----: | :---------- | :-----------: | ---------: | :-----------------: |
| Alabama  |   AL   | Montgomery  |     1846      |     205764 |         No          |
| Alaska   |   AK   | Juneau      |     1906      |      31275 |         No          |
| Arizona  |   AZ   | Phoenix     |     1889      |    1445632 |         Yes         |
| Arkansas |   AR   | Little Rock |     1821      |     193524 |         Yes         |

Doxygen はこれを次のようにレンダリングします。

サンプル

于 2013-03-16T05:29:08.977 に答える
1

最近のプロジェクトでは、Markdown をプログラムで作成する必要があったため、ライブラリを作成して GitHub に投稿しました。うまくいけば、あなたはそれが役に立つと思うでしょう.

このプロジェクトはMarkdownLogと呼ばれ、コレクションや辞書などの .NET データ構造から Markdown を生成できる、軽量 (つまり、最小限の依存関係) でポータブルな .NET ライブラリ (PCL) です。診断目的でプログラムの内部データ構造をログに記録するために使用しますが、ニーズも満たす必要があります。

コレクションから Markdown テーブルを作成する方法は次のとおりです。

var data = new[]
{
    new{Year = 1991, Album = "Out of Time", Songs=11, Rating = "* * * *"},
    new{Year = 1992, Album = "Automatic for the People", Songs=12, Rating = "* * * * *"},
    new{Year = 1994, Album = "Monster", Songs=12, Rating = "* * *"}
};

Console.Write(data.ToMarkdownTable());

// Produces:
//
//     Year | Album                    | Songs | Rating   
//     ----:| ------------------------ | -----:| --------- 
//     1991 | Out of Time              |    11 | * * * *  
//     1992 | Automatic for the People |    12 | * * * * *
//     1994 | Monster                  |    12 | * * *    

この出力が GitHub フレーバーの Markdown パーサーで解析されると、HTML テーブルが生成されることに注意してください。

デフォルトでは、列はデータ型に基づいて配置され (数値は右揃え、文字列は左揃え)、ヘッダー名はオブジェクトのプロパティ名から生成されます。これが望ましくない場合は、出力をより細かく制御できるオーバーライドがいくつかあります。

すべての標準 Markdown 要素GFM テーブルのサポートが組み込まれています。また、必要な要素タイプ (棒グラフ、iOS UITableView) をいくつか追加しました。これらはコード ブロックとして実装されているため、Markdown 標準に引き続き準拠しています。

最近コードを GitHub にアップロードしたばかりなので、ドキュメントは今のところ基本的なものです。そうは言っても、プロジェクトには多くの単体テストがあり、それがどのように機能するかを示す必要があります。

この質問が出されてからしばらく経ちましたが、このプロジェクトが誰かの役に立つことを願っています。

于 2014-07-08T17:33:56.093 に答える