LINQ转换为列表对象

本文关键字:对象 列表 转换 LINQ | 更新日期: 2023-09-27 18:15:51

我使用以下代码返回一个illist:

FileName = Path.GetFileName(files[i]);
IList<DataX> QueryListFromFTP = DataX.GetListFromFTP(FileName);
QueryListFromFTP = (IList<DataX>)QueryListFromFTP
    .Select(x => new { x.user_id, x.date, x.application_ID })
    .ToList()
    .Distinct();

但是我一直得到这个错误:

无法强制转换类型为'd__7a 1[<>f__AnonymousType0 3 '的对象[System. string,System. string,System. string]。

输入"System.Collections.Generic.IList"1[DataXLibrary.DataX]。

我做错了什么?

LINQ转换为列表对象

如果你想要的是List <你只需要:

IList<DataX> QueryListFromFTP = DataX.GetListFromFTP(FileName).Distinct().ToList();
// Use QueryListFromFTP here.

如果你想要一个不同类型对象的List作为你的。select的结果,那么你需要将结果存储在该类型对象的List中,也就是匿名的

下面这行在c#中创建了一个匿名类型,它与Datax类型不对应:

new { x.user_id, x.date, x.application_ID })

你应该这样修改:

Select(x => new Datax(){User_id = x.user_id, Date = x.date, Application = x.application_ID })

你的代码有两个问题:

  1. 您正在将DataX对象的List转换为"匿名类型对象"(new { x.user_id, x.date, x.application_ID })。

  2. 此对象与DataX类型不同,不能自动强制返回到DataX对象。
  3. 试着读一下字里行间,看起来你想要一个不同的DataX对象列表,其中的区别是由DataX对象的属性子集决定的。因此,您必须回答这个问题,如何处理在其他属性中具有不同数据的副本(根据此定义)?你必须抛弃其中的一些。Distinct()不是合适的工具,因为它只适用于它所应用的IEnumerable的整个对象。

这几乎就像你需要一个DistinctBy,其中一个参数给出计算独特性的属性,第二个参数给出一些逻辑来决定选择哪些非独特性的"重复"。但是这可以通过多个IEnumerable方法来实现:GroupBy和从每个结果组中选择适当的单个项目d的进一步表达式。这里有一个可能的解决方案:

FileName = Path.GetFileName(files[i]);
IList<DataX> QueryListFromFTP = DataX.GetListFromFTP(FileName)
   .GroupBy(datax => new { datax.user_id, datax.date, datax.application_ID })
   .Select(g => g.First()); // or another expression to choose one item per group
   .ToList();

如果,例如,有一个version字段,您想要每个"副本"的最近的一个,您可以:

.Select(g => g.OrderByDescending(datax => data.version).First())
但是,请注意,如果您只是想要对象的所有属性的独特性,并且不需要选择一个特定的值(为了在丢弃一些被认为是重复的对象后获得其附加属性),那么它可能像这样简单:

IList<DataX> QueryListFromFTP = DataX.GetListFromFTP(FileName)
   .Distinct()
   .ToList();

我进一步建议您在可能的情况下使用IReadOnlyCollection(即.ToList().AsReadOnly()),并且根据您的数据,您可能希望使用GetListFromFTP函数来执行重复数据删除/区分。

为了回答任何关于GroupBy不是正确答案的担忧,因为它可能表现得不够好,这里有一种替代方法来处理这个问题(尽管我全心全意地不同意你的观点——直到测试证明它很慢,这是一个完美的答案)。

// in a static helper class of some kind
public static IEnumerable<T> DistinctBy<T, TKey>(
    this IEnumerable<T> source,
    Func<T, TKey> keySelector
) {
   if (source == null) {
      throw new ArgumentNullException("source", "Source enumerable cannot be null.");
   }
   if (keySelector == null) {
      throw new ArgumentNullException("keySelector", "keySelector function cannot be null. To perform a generic distinct, use .Distinct().");
   }
   return DistinctByImpl(source, keySelector);
}
private static IEnumerable<T> DistinctByImpl<T, TKey>(
    this IEnumerable<T> source,
    Func<T, TKey> keySelector
) {
   HashSet<TKey> keys = new HashSet<TKey>();
   return source.Where(s => keys.Add(keySelector(s)));
}

它是这样使用的:

public class Animal {
   public string Name { get; set; }
   public string AnimalType { get; set; }
   public decimal Weight { get; set; }
}
IEnumerable<Animal> animals = new List<Animal> {
    new Animal { Name = "Fido", AnimalType = "Dog", Weight = 15.0M },
    new Animal { Name = "Trixie", AnimalType = "Dog", Weight = 15.0M },
    new Animal { Name = "Juliet", AnimalType = "Cat", Weight = 12.0M },
    new Animal { Name = "Juliet", AnimalType = "Fish", Weight = 1.0M }
};
var filtered1 = animals.DistinctBy(a => new { a.AnimalType, a.Weight });
/* returns:
Name   Type Weight
Fido   Dog  15.0
Juliet Cat  12.0
Juliet Fish 1.0
*/
var filtered2 = animals.DistinctBy(a => a.Name); // or a simple property
/* returns:
Name   Type Weight
Fido   Dog  15.0
Trixie Dog  15.0
Juliet Cat  12.0
*/