2012-01-06 19 views
0

私はリストに変換した2つのExcelファイルを持っています。 1番目のファイルには、必要なすべてのアイテムの完全なリストがあります。ただし、2番目のリストには、最初のリストで変更する必要がある項目の小さなリストがあります。2つのLINQ辞書を1つに結合するには?

IEnumerable<ExcelRow> queryListA = from d in datapullList 
              select new ExcelRow 
              { 
               Company = d.GetString(0), 
               Location = d.GetString(1), 
               ItemPrice = d.GetString(4), 
               SQL_Ticker = d.GetString(15) 
              }; 

第二のリストは非常によく似た方法で構築されています:

IEnumerable<ExcelRow> queryListB = from dupes in dupespullList 
              select new ExcelRow 
              { 
               Company = d.GetString(0), 
               Location = d.GetString(1), 
               NewCompany = d.GetString(4) 
              }; 

だから、同社が一致した第一のリスト内の特定の場所からが存在する場合 は、ここに私の第一のリストが構築される方法です2番目のリストの場合、会社は新会社名に変更されます。

次に、最終リストには1番目のリストのすべてが含まれている必要がありますが、2番目のリストから指定された変更があります。

私はこれで数日間は苦労しました。詳細が必要な場合はお知らせください。

[更新:]私はLINQとC#でかなり新しいです。私はこのコードをOffice 2003のExcelリーダーに関するWeb上で見つけました。上記のすべてのクラスから1つのリストを作成するにはどうすればよいですか? マイExcelRowクラス:

class ExcelRow 
{  
    List<object> columns; 

    public ExcelRow() 
    { 
     columns = new List<object>(); 
    } 

    internal void AddColumn(object value) 
    { 
     columns.Add(value); 
    } 

    public object this[int index] 
    { 
     get { return columns[index]; } 
    } 

    public string GetString(int index) 
    { 
     if (columns[index] is DBNull) 
     { 
      return null; 
     } 
     return columns[index].ToString(); 
    } 

    public int Count 
    { 
     get { return this.columns.Count; } 
    } 
} 

マイExcelProviderクラス:

class ExcelProvider : IEnumerable<ExcelRow> 
{ 
    private string sheetName; 
    private string filePath; 
    private string columnName1; 
    private string columnName2; 
    private List<ExcelRow> rows; 

    public ExcelProvider() 
    { 
     rows = new List<ExcelRow>(); 
    } 

    public static ExcelProvider Create(string filePath, string sheetName, string columnName1, string columnName2) 
    { 
     ExcelProvider provider = new ExcelProvider(); 
     provider.sheetName = sheetName; 
     provider.filePath = filePath; 
     provider.columnName1 = columnName1; 
     provider.columnName2 = columnName2; 
     return provider; 
    } 

    private void Load() 
    {    
     string connectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties= ""Excel 8.0;HDR=YES;IMEX=1""";    
     connectionString = string.Format(connectionString, filePath); 
     rows.Clear(); 
     using (OleDbConnection conn = new OleDbConnection(connectionString)) 
     { 
      try 
      { 
       conn.Open(); 
       using (OleDbCommand cmd = conn.CreateCommand()) 
       { 
        cmd.CommandText = string.Format("SELECT * FROM [{0}$] WHERE {1} IS NOT NULL AND {2} <> \"{3}\"", sheetName, columnName1, columnName2, null); 
        using (OleDbDataReader reader = cmd.ExecuteReader()) 
        { 
         while (reader.Read()) 
         { 
          ExcelRow newRow = new ExcelRow(); 
          for (int count = 0; count < reader.FieldCount; count++) 
          { 
           newRow.AddColumn(reader[count]); 
          } 
          rows.Add(newRow); 
         } 
        } 
       } 
      } 
      catch (Exception ex) 
      { throw ex; } 
      finally 
      { 
       if (conn.State == System.Data.ConnectionState.Open) 
        conn.Close(); 
      } 
     } 
    } 

    public IEnumerator<ExcelRow> GetEnumerator() 
    { 
     Load(); 
     return rows.GetEnumerator(); 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     Load(); 
     return rows.GetEnumerator(); 
    } 
} 

だから、すべてこのロジックを使用して、どのように私は私の問題を解決することができますか?

答えて

1
//first create a dictionary of comapny whose name has been changed 
    var dict = queryListB.ToDictionary(x => x.Company, y => y.NewCompany); 

    //loop on the first list and do the changes in the first list 
    queryListA.ForEach(x => 
         { 
          if(dict.Keys.Contains(x.Company)) 
           x.Company = dict[x.Company]; 
         }); 
+0

私はOPは同様に場所の一致を求めていると思う:「だから、会社が特定の場所から**がある場合**第二に一致する第一のリストでは、新しい会社名 " – Joey

+0

に変更されます。そうです、それは私が必要とするものです。 @ Joeyの説明をありがとう。 –

0

同じ目標を達成するために簡単なコードを書くことはできますが、最初のリストと2番目のリストを反復する回数を減らす方法があります。パフォーマンスが問題でない場合、datapullList内の各要素についてdupespullListを検索するより簡単な方法が適切かもしれません。

var excelRowCreator = new ExcelRowCreator(dupespullList); 
var finalRows = excelRowCreator.CreateExcelRows(datapullList); 

// ... 

public class ExcelRowCreator 
{ 
    /// <summary> 
    /// First key is company name, second is location 
    /// and final value is the replacement name. 
    /// </summary> 
    private readonly IDictionary<string, IDictionary<string, string>> nameReplacements; 

    /// <summary> 
    /// I don't know what type of objects your initial 
    /// lists contain so replace T with the correct type. 
    /// </summary> 
    public ExcelRowCreator(IEnumerable<T> replacementRows) 
    { 
     nameReplacements = CreateReplacementDictionary(replacementRows); 
    } 

    /// <summary> 
    /// Creates ExcelRows by replacing company name where appropriate. 
    /// </summary> 
    public IEnumerable<ExcelRow> CreateExcelRows(IEnumerable<T> inputRows) 
    { 
     // ToList is here so that if you iterate over the collection 
     // multiple times it doesn't create new excel rows each time 
     return inputRows.Select(CreateExcelRow).ToList(); 
    } 

    /// <summary> 
    /// Creates an excel row from the input data replacing 
    /// the company name if required. 
    /// </summary> 
    private ExcelRow CreateExcelRow(T data) 
    { 
     var name = data.GetString(0); 
     var location = data.GetString(1); 

     IDictionary<string, string> replacementDictionary; 
     if (nameReplacements.TryGetValue(name, out replacementDictionary)) 
     { 
      string replacementName; 
      if (replacementDictionary.TryGetValue(location, out replacementName)) 
      { 
       name = replacementName; 
      } 
     } 

     return new ExcelRow 
     { 
      Company = name, 
      Location = location, 
      ItemPrice = data.GetString(4), 
      SQL_Ticker = data.GetString(15) 
     }; 
    } 

    /// <summary> 
    /// A helper method to create the replacement dictionary. 
    /// </summary> 
    private static IDictionary<string, IDictionary<string, string>> CreateReplacementDictionary(IEnumerable<T> replacementRows) 
    { 
     var replacementDictionary = new Dictionary<string, IDictionary<string, string>>(); 
     foreach (var dupe in replacementRows) 
     { 
      var name = dupe.GetString(0); 
      IDictionary<string, string> locationReplacements; 
      if (!replacementDictionary.TryGetValue(name, out locationReplacements)) 
      { 
       locationReplacements = new Dictionary<string, string>(); 
       replacementDictionary[name] = locationReplacements; 
      } 

      locationReplacements[dupe.GetString(1)] = dupe.GetString(4); 
     } 

     return replacementDictionary; 
    } 
} 

UPDATE:クラスとしてパッケージ化し、任意の文法の誤りがあってはならないので、Visual Studioで書かれました。

+0

私の答えはちょっと無視しましたが、名前の変更と同じ場所と名前を持つという会社の要件に気がつきました。私のソリューションを更新して、これをチェックします。 – Joey

+0

回答が更新されました。 – Joey

1

queryListAをループし、queryListBに一致する会社があるかどうかを確認します。その場合は、Companyプロパティを更新します。

ここでは、コードです:

foreach (var companyA in queryListA) 
{ 
    var companyBMatch = queryListB.FirstOrDefault(x => x.Company == companyA.Company && x.Location == companyA.Location); 
    if (companyBMatch != null) 
    companyA.Company = companyBMatch.NewCompany; 
} 
+0

これでも他のアイテムはすべてリストに残っていますか、それとももう一度ビルドする必要がありますか? –

+0

はい、それでも他の項目は保持されます。 – Paul

+0

これは初心者の質問です。どのようにループからリストを構築できますか? –