挑战:优雅地LINQify此程序代码

挑战:优雅地LINQify此程序代码,linq,linq-to-objects,Linq,Linq To Objects,但这是不雅观的,在评论栏中填充内容看起来像个婊子。现在,我很高兴保持程序性,但我认为,看看人们是否能想出真正聪明的东西可能是一个有趣的挑战。请原谅我没有真正着手编写这篇文章,但我会这样做: var cookieMap = (filesOfType1.Select(file => GetType1FileCookiePair(file)) .Concat(filesOfType2.Select(file => GetType2FileCookiePair

但这是不雅观的,在评论栏中填充内容看起来像个婊子。现在,我很高兴保持程序性,但我认为,看看人们是否能想出真正聪明的东西可能是一个有趣的挑战。

请原谅我没有真正着手编写这篇文章,但我会这样做:

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);
以下是:

好好爱我,林克

编辑:添加了一个将吞咽所有异常的吞咽方法。 编辑2:编译、修改等。添加。现在一切正常。
请原谅,我没有真正着手编写,但我会这样做:

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);
以下是:

好好爱我,林克

编辑:添加了一个将吞咽所有异常的吞咽方法。 编辑2:编译、修改等。添加。现在一切正常。 编辑:更新cookie检索以满足类型1的文件比类型2的文件更重要


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

以下是我的尝试-似乎最简单的方法是将任务分成三个不同的语句

我使用了一个helper函数,如果操作抛出异常,它将返回null——为了与Omer van Kloeten的答案保持一致,我将此函数称为Swallow

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

最后,请注意,这是未编译的,因此将其视为意图

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;
  } );

这是我的尝试——将任务分成三个不同的语句似乎是最简单的

我使用了一个helper函数,如果操作抛出异常,它将返回null——为了与Omer van Kloeten的答案保持一致,我将此函数称为Swallow

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

最后,请注意,这是未编译的,因此将其视为意图

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;
  } );

此外,我认为Max将返回一个double.Edited re异常。IIRC,Max有一个通用重载。而且我认为Max会返回一个双重的。编辑过的re异常。IIRC,Max有一个泛型重载。从我所看到的,您显示的原始代码不满足类型1的文件比类型2约束的文件更重要-如果类型2文件的计数更高,代码将覆盖类型1 cookie容器。哦,很好的捕获,谢谢Bevan!从我所看到的,您显示的原始代码不满足类型1的文件比类型2约束的文件更重要-如果类型2文件具有更高的计数,代码将覆盖类型1 cookie容器。噢,很好的捕获,谢谢Bevan!其中pair=>!pairsOfType1.Containsp=>p.Key==pair.Key;是不正确的,因为它会在不检查的情况下过滤掉type2中计数较高的对。请检查原始问题-类型1的Domenic编写的文件比类型2的文件更重要,因此Where子句是正确的,尽管原始代码不满足此要求。为什么需要在何处调用类型2?一个&&条件还不够吗?@Hosam-是的,我可以使用&&而不是两个Where调用,将产生相同的效果;我更喜欢一系列简单的测试,而不是一个更复杂的测试。这是一个聪明的小精灵,尤其是第三部分+1.其中pair=>!pairsOfType1.Containsp=>p.Key==pair.Key;是不正确的,因为它会在不检查的情况下过滤掉type2中计数较高的对。请检查原始问题-类型1的Domenic编写的文件比类型2的文件更重要,因此Where子句是正确的,尽管原始代码不满足此要求。为什么需要在何处调用类型2?一个&&条件还不够吗?@Hosam-是的,我可以使用&&而不是两个Where调用,将产生相同的效果;我更喜欢一系列简单的测试,而不是一个更复杂的测试。这是一个聪明的小精灵,尤其是第三部分+1.
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;
  } );
// 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);