1

文字列の行を含むファイルがあります。各行は、キー値のコレクションを表します。次に例を示します。

Name=JUI;Type=HomeUser;Address=Belgium;Address=Liege;Address=Street
Name=Tim;Type=HomeUser;Address=Belgium;Address=Hasselt;Address=Street
Name=Kim;Type=Proff;Address=Germany;Address=Dusseldorf;Address=Street
Name=Ils;Type=Proff;Address=Germany;Address=Munich;Address=Street
Name=Jan;Type=Student;Address=Germany;Address=Frankfurt;Address=Street
Name=Dav;Type=Student;Address=France;Address=Mitz;Address=Street
Name=Soli;Type=HomeUser;Address=France;Address=Lyon;Address=Street
Name=Mik;Type=HomeUser;Address=Switzerland;Address=Zurich;Address=Street
Name=Peter;Type=Blocked;Address=Netherland;Address=Enschede;Address=Street 
Name=Maz;Type=Blocked;Address=Germany;Address=Achen;Address=Street
Name=Jo;Type=Teacher;Address=Belgium;Address=Antwerpen;Address=Street

どうすれば次のことができますか?

  1. タイプがHomeUserである名前を取得します
  2. Address = Germanyのタイプを取得します(earch行に3つのアドレスキーがあるという問題)
  3. address=Lyonの名前を取得します

それを行う簡単な方法はありますか?

4

5 に答える 5

4

これらすべての場合において、より良いデータ表現があれば、答えは本当に簡単です。LINQを使用するだけです。

ただし、最初のステップはデータを解析することです。次のようにモデル化します。

public class User // ???
{
    public string Name { get; private set; }
    public string Type { get; private set; } // Should this be an enum?
    public IList<string> Addresses { get; private set; }

    // Could make this a constructor if you really want... I like the
    // explicit nature of the static factory method.
    public static User ParseLine(string line)
    {
        // TODO: Split line into components etc
    }
}

クエリを取得するList<User>と非常に簡単になりますが、「データをより自然な表現にする」と「データを使って興味深い操作を行う」を区別することが重要です。

これは、この特定の例よりもはるかに一般的なポイントですが、常にデータをできるだけ早く自然で有用な表現に変換し、可能な限りその表現に保持するようにしてください。可能であれば、コードの境界で厄介な表現(通常は文字列)のみを処理します。

于 2013-01-31T14:27:44.970 に答える
3

アイテムを解析するための正規表現を作成します。"Name=(.+?);Type=(.+?);Address=(.+?) etc." 次に、すべての情報を保持するクラスを作成できます。

class Record { public string Name; public string Type; public string Address; public string Address2; public string Address3}

次に、各行を正規表現と照合し、Matchグループのフィールドに入力して、クラスのインスタンスを作成し、これらをに追加しList<Record> recordsます。

これで、linqを使用して次の検索を簡単に行うことができます。

  1. タイプはHomeUser:records.Where(p => p.Type == "HomeUser")
  2. 住所はドイツ:records.Where(p => p.Address == "Germany")
  3. アドレスはリヨンです:records.Where(p => p.Address == "Lyon")

この例を簡単に拡張して、3つのアドレスフィールドすべてを調べることができます

于 2013-01-31T14:28:33.527 に答える
0

正規表現を使用して、トークンを後方参照と照合できると思います。

このチュートリアルをチェックしてください。

于 2013-01-31T14:26:45.970 に答える
0

最初に構造体を定義する方が簡単です

struct MyStruct
{
    public string Name, Type /* etc.*/ ;
}

その後、入力を分割する必要があります

string[] arrayOfInputs = inpuString.Split(new char[]{Environment.NewLine, '\n', '\r'}) // splits your input, such that every element represents a line
List<MyStruct> myStruct = new List<MyStruct>;
foreach (string s in arrayOfInputs)
{
    string[] arrayOfFields = s.Split(';');
    // arrayOfFields[0] == "Name=name"
    // arrayOfFields[1] == "Type=type"
    // etc. extract needed info
    myStruct.Add(new MyStruct(/* arguments go here */))
}

データを抽出して構造体のリストに追加したので、Linqを使用して必要なデータを検索できます。

string theNameImLookingFor = from element in myStruct
                             where element.Type == "HomeUser"
                                || element.Address[0] == "Lyon"
                                || element.Address[1] == "Lyon"
                                || element.Address[2] == "Lyon"
                             select element.Name;

string theTypeImLookingFor = from element in myStruct
                             // etc.
                             select element.Type;

または、次のようにすることもできます。

string tNILF = myStruct.Where(element => element.Type == "HomeUser" /* || etc. */).Select(element => element.Name);
于 2013-01-31T14:52:01.043 に答える
0

これを行う1つの方法は、キーと値のペアを動的オブジェクトのコレクションに読み込むことです。これが完了すると、動的ランタイムを使用して、LINQを使用して動的オブジェクトをクエリできます。

動的オブジェクトのコレクションを作成するには:

var users = str.Split("\r\n".ToArray(), StringSplitOptions.RemoveEmptyEntries)
                .Select(x => x.Split(';')
                    .Select(p => p.Split('='))
                    .ToLookup(s => s[0], s => s[1])
                    .ToDictionary(l => l.Key, l => (l.Count() > 1) 
                        ? (object)l.ToList() : (object)l.First())
                    .ToExpando());

この拡張メソッドの使用に注意してください。

public static dynamic ToExpando(this IDictionary<string, object> dict)
{
    IDictionary<string, object> expando = new ExpandoObject();
    foreach (var kv in dict)
        expando[kv.Key] = kv.Value;
    return expando;
}

次に、関心のあるクエリを実行できます。

1.タイプがHomeUserである名前を取得します。

var homeUsers = users.Where(u => u.Type == "HomeUser")
    .Select(u => u.Name);

2. Address = Germany(注:.Addressはa List<string>)であるタイプを取得します。

var typesInGermany = users.Where(u=>u.Address.Contains("Germany"))
    .Select(u => u.Type).Distinct();

3.アドレス=Lyonの名前を取得します。

var namesInLyon = users.Where(u => u.Address.Contains("Lyon"))
    .Select(u => u.Name);
于 2013-01-31T16:25:40.637 に答える