1

次のようなテーブルがあるとしましょう。

{
   value = 4
},
{
   value = 3
},
{
   value = 1
},
{
   value = 2
}

これを反復処理して値を順番に出力したいので、出力は次のようになります。

1
2
3
4

これを行うにはどうすればよいですか、 ipairsand pairs、 andの使用方法は理解していますtable.sortが、それは table.insert を使用していてキーが有効な場合にのみ機能します。これを値の順にループする必要があります。

カスタム関数を試しましたが、単に間違った順序で出力されました。

私が試してみました:

  • インデックスの作成とそのループ
  • テーブルの並べ替え (エラーをスロー: テーブルとテーブルで __lt を実行しようとします)
  • 並べ替え、インデックス、およびその他のテーブルの組み合わせにより、機能しないだけでなく、非常に複雑になりました。

私は元気で、本当に困惑しています。

4

2 に答える 2

2

テーブルの並べ替え

これは正しい解決策でした。

(エラーをスローします: テーブルとテーブルで __lt を実行しようとします)

を使おうとしたようですねa < b

Lua が値をソートできるようにするには、値を比較する方法を知っている必要があります。数値と文字列を比較する方法を知っていますが、デフォルトでは 2 つのテーブルを比較する方法を知っています。このことを考慮:

local people = {
    { name = 'fred', age = 43 },
    { name = 'ted', age = 31 },
    { name = 'ned', age = 12 },
}

私が人を呼んsortだ場合、Lua は私の意図をどのように知ることができますか? 「年齢」または「名前」が何を意味するのか、またはどちらを比較に使用したいのかわかりません。私はそれを言わなければなりません。

Lua にテーブルに対する演算子の意味を伝えるメタテーブルをテーブルに追加することは可能ですが、2 つのオブジェクトを比較する方法を伝えるコールバック関数を<提供することもできます。sort

2 つの値を受け取るsort関数を指定し、テーブルの知識を使用して、最初の値が 2 番目の値よりも「小さい」かどうかを返します。あなたのテーブルの場合:

table.sort(t, function(a,b) return a.value < b.value end)

for i,entry in ipairs(t) do
    print(i,entry.value)
end
于 2015-08-11T15:27:10.813 に答える
0

元のテーブルを変更せずに残したい場合は、次のようなカスタムの「値による並べ替え」反復子を作成できます。

local function valueSort(a,b)
    return a.value < b.value;
end

function sortByValue( tbl ) -- use as iterator
    -- build new table to sort
    local sorted = {};
    for i,v in ipairs( tbl ) do sorted[i] = v end;
    -- sort new table
    table.sort( sorted, valueSort );
    -- return iterator
    return ipairs( sorted );
end

が呼び出されると、新しいテーブルsortByValue()にクローンが作成され、並べ替えられたテーブルが並べ替えられます。次に、テーブルを に渡し、ループで使用される反復子を出力します。tblsortedsortedipairs()ipairsfor

使用するには:

for i,v in sortByValue( myTable ) do
  print(v)
end

これにより、元のテーブルが変更されないことが保証されますが、反復を行うたびにmyTable、新しいsortedテーブルを作成するために反復子が複製し、次にtable.sortそのsortedテーブルを作成する必要があるという欠点があります。

sortByValue()パフォーマンスが重要な場合は、イテレータによって実行される作業を「キャッシュ」することで大幅に高速化できます。更新されたコード:

local resort, sorted = true;

local function valueSort(a,b)
    return a.value < b.value;
end

function sortByValue( tbl ) -- use as iterator
    if not sorted then -- rebuild sorted table
        sorted = {};
        for i,v in ipairs( tbl ) do sorted[i] = v end;
        resort = true;
    end
    if resort then -- sort the 'sorted' table
        table.sort( sorted, valueSort );
        resort = false;
    end
    -- return iterator
    return ipairs( sorted );
end

myTablesetに要素を追加または削除するたびにsorted = nil。これにより、反復子は、テーブルを再構築する必要があることを認識できますsorted(また、再ソートも行います)。

valueネストされたテーブルのいずれかでプロパティを更新するたびに、 を設定しresort = trueます。これにより、イテレータはtable.sort.

これで、反復子を使用すると、キャッシュされたsortedテーブルから以前に並べ替えられた結果を再利用しようとします。

テーブルが見つからない場合sorted(たとえば、イテレータを最初に使用したとき、またはsorted = nil再構築を強制するように設定したため)、テーブルを再構築します。リソートする必要があると判断した場合 (たとえば、最初の使用時、sortedテーブルが再構築された場合、または を設定した場合resort = true)、テーブルをリソートしsortedます。

于 2015-08-23T14:38:05.663 に答える