1
string[] filesOfType1 = GetFileList1();
string[] filesOfType2 = GetFileList2();
var cookieMap = new Dictionary<string, CookieContainer>();

Action<string, Func<string, KeyValuePair<string, CookieContainer>>> addToMap = (filename, pairGetter) =>
    {
        KeyValuePair<string, CookieContainer> cookiePair;
        try
        {
            cookiePair = pairGetter(filename);
        }
        catch
        {
            Console.WriteLine("An error was encountered while trying to read " + file + ".");
            return;
        }

        if (cookieMap.ContainsKey(cookiePair.Key))
        {
            if (cookiePair.Value.Count > cookieMap[cookiePair.Key].Count)
            {
                cookieMap[cookiePair.Key] = cookiePair.Value;
            }
        }
        else
        {
            cookieMap.Add(cookiePair.Key, cookiePair.Value);
        }
    };


foreach (string file in filesOfType1)
{
    addToMap(file, GetType1FileCookiePair);
}
foreach (string file in filesOfType2)
{
    addToMap(file, GetType2FileCookiePair);
}

必须保留的显着特征:

  • 类型 1 的文件比类型 2 的文件更重要;即,如果类型 1 的文件映射到 (key, value1) 组合,类型 2 的文件映射到 (key, value2) 组合,那么我们将 (key, value1) 添加到 cookieMap 而不是(key, value2)。编辑:正如 Bevan 所指出的,我原来的程序代码对此并不满意。
  • 其次,具有更高优先级CookieContainer的 sCount具有更高的优先级,即如果同一键有两个(键,值)组合并且都来自相同的文件类型,我们选择具有更高的一个value.Count
  • 每个案例的异常处理是必须的;搞砸一个文件阅读应该只是让我们注意到这一点并继续。

我最好的尝试是这样开始的:

var cookieMap = (filesOfType1.Select(file => GetType1FileCookiePair(file))
                .Concat(filesOfType2.Select(file => GetType2FileCookiePair(file))))
                    .GroupBy(pair => pair.Key)
                    .Select(/* some way of selecting per the above bullets */)
                    .ToDictionary(pair => pair.Key, pair => pair.Value);

但这很不雅,并且填写该评论块似乎是个婊子。现在我很高兴保持程序化,但我认为看看人们是否能想出一些非常聪明的东西可能是一个有趣的挑战。

4

3 回答 3

3

这是我的尝试 - 将任务分成三个不同的陈述似乎最简单。

我正在使用一个辅助函数,如果操作引发异常,则返回 null - 为了与 Omer van Kloeten 的答案保持一致,我称之为 Swallow()

另外,我没有使用 LINQ 语法,只是 System.Linq.Enumerable 提供的扩展方法

最后,请注意这是未编译的 - 所以将其视为意图。

// Handle all files of type 1
var pairsOfType1 = 
    filesOfType1
        .Select( file => Swallow( pairGetter(file)))
        .Where( pair => pair != null);

// Handle files of type 2 and filter out those with keys already provided by type 1
var pairsOfType2 =
    filesOfType2
        .Select( file => Swallow( pairGetter(file)))
        .Where( pair => pair != null);
        .Where( pair => !pairsOfType1.Contains(p => p.Key == pair.Key));

// Merge the two sets, keeping only the pairs with the highest count
var cookies =
    pairsOfType1
        .Union( pairsOfType2)
        .GroupBy( pair => pair.Key)
        .Select( group => group.OrderBy( pair => pair.Value.Count).Last());
        .ToDictionary( pair => pair.Key);
于 2008-10-27T08:25:17.277 回答
2
using CookiePair = KeyValuePair<string, CookieContainer>;
using CookieDictionary = Dictionary<string, CookieContainer>;

Func<string[], Func<string, CookiePair>, IEnumerable<CookiePair>> getCookies =
  ( files, pairGetter ) =>
    files.SelectMany( filename => {
      try { return new[] { pairGetter( filename ) }; }
      catch { Console.WriteLine( "..." ); return new CookiePair[0]; }
    } );

var type1Cookies = getCookies( filesOfType1, GetType1FileCookiePair ).ToArray( );
var type1CookieNames = type1Cookies.Select( p => p.Key ).ToArray( );
var type2Cookies = getCookies( filesOfType2, GetType2FileCookiePair )
  .Where( p => !type1CookieNames.Contains( p.Key ) );

var cookieMap = type1Cookies.Concat( type2Cookies )
  .Aggregate( new CookieDictionary( ), ( d, p ) => {
    if( !d.ContainsKey( p.Key ) || p.Value.Count > d[p.Key].Count )
      d[p.Key] = p.Value;
    return d;
  } );

编辑:更新 cookie 检索以满足“类型 1 的文件比类型 2 的文件更重要”的要求。

于 2008-10-27T00:38:52.273 回答
1

请原谅我实际上并没有继续编译它,但这是我要做的方式:

var cookieMap = (from pair in
                     (from f1 in filesOfType1
                      select Swallow(() => GetType1FileCookiePair(f1)))
                         .Concat(from f2 in filesOfType2
                                 select Swallow(() => GetType2FileCookiePair(f2)))
                         .SelectMany(dict => dict)
                 group pair by pair.Key into g
                 select g)
                .ToDictionary(g => g.Key, g => g.Select(pair => pair.Value)
                                                .OrderByDescending(value => value.Count)
                                                .First());

Swallow如下:

private static T Swallow<T>(Func<T> getT)
{
    try { return getT(); } catch { }

    return default(T);
}

爱我一个好的LINQ。

  • 编辑:添加了一个Swallow可以吞下所有异常的方法。
  • 编辑 2:编译、更改等。添加Swallow. 现在按预期工作。
于 2008-10-26T22:36:24.613 回答