2016-05-13 88 views
2

我有一个这样的文件:填充列表<Object>使用LINQ

City|Country|Phone Number 
Name 
City|Country|Phone Number 
Name 
City|Country|Phone Number 
Name 

等等...

我做了一个类:

class Person 
{ 
string city, country, phone, name; 
} 

阅读这个大后文件,我想创建一个List并将所有值放在它们各自的字段中。

我的工作至今

List<PersonObj> objectsList = new List<PersonObj>(); 

string[] peopleFile = System.IO.File.ReadAllLines(fileName); 

var oddLines = peopleFile.Where((src, index) => index % 2 != 0); 
var evenLines = peopleFile.Where((src, index) => index % 2 == 0); 

和其分别成功获取地址和名称分别线在oddLinesevenLines

我想要的东西

我应该objectsList填充使用LINQ,而不是使用循环

非常感谢您的帮助

+0

你是什么意思 “在一线” 是什么意思? –

+0

@BrianMains哦,我的意思是直接使用LINQ。我已更新问题 –

回答

2

这应该做你想要

什么填充它们一个接一个
var people = File.ReadLines(fileName) 
    .Select((l,i) => new { Line = l.Split('|'), LineNo = i }) 
    .GroupBy(x => x.LineNo/2) 
    .Select(grp => new Person 
     { 
      city = grp.First().Line[0], 
      country = grp.First().Line.Skip(1).FirstOrDefault(), 
      phone = grp.First().Line.Skip(2).FirstOrDefault(), 
      name = grp.Last().Line[0] 
     }) 
    .ToList(); 

基本上你使用Select的超负荷给出是你的索引,这将允许你按行号进行分组,这样你就可以得到前两行的组合,接下来的两行,等等。然后只需从组中的第一行或最后一行(应该只有2)和从分割中得到数组的索引。

注意,这会给不正确的结果,如果文件不匹配的格式,如namecity是最后进入相同的,如果文件中有一个奇数行或countryphone被空如果奇数行不具有至少两个管道字符。

此外,我用File.ReadLines而不是File.ReadAllLines来避免创建不需要的中间数组。

+0

谢谢!检查后我会回复你 –

+0

它在索引的使用上给出错误。错误读为:不能用[]将索引应用于'Anonymous Type#1'类型的表达式 –

+0

@TalhaIrfan我不好,我现在通过引用我创建的匿名类的'Line'属性来解决这个问题。 – juharr

1

您可以使用Zip来做到这一点。我假设evenLines包含城市等和oddLines的名称。

var persons = oddLines.Zip(
    evenLines.Select(line => line.Split('|')), 
    (name, data) => new Person {name = name, city = data[0], country = data[1], phone = data[2]});     

Zip结合的evenLines对应线的oddLines每一行。第二行被|拆分,并且对于每个组合,将生成一个新的Person对象并填充其数据。

当然,应该有更多的错误处理,因为如果文件中缺少值,这可能会引发异常。

+0

谢谢勒内。是的,由于数据不完整或丢失而容易出错,但真的很聪明。我会尝试 –

1

关注更好的分离,可以首先将二者结合起来的结果oddLinesevenLines创建一个完整的string

var lines = from o in oddLines 
      from ev in evenLines 
      select o + "|" + ev; 

,然后用双LINQSelect

objectsList = lines.Select(x => x.Split('|')) 
    .Select(y => new PersonObj() { 
     city = y[0], 
     country = y[1], 
     phone = y[2], 
     name = y[3], 
    }).ToList(); 

第一Select将用于将文件中的每一行分割为4个元素的string[],第二个Select用于将cr eate PersonObj项目从他们。

请注意,您必须将您的字段(city, country, phone, name)设置为public而不是private来执行此操作。

+1

'名称'是在不同的行,所以这是行不通的。 – juharr

+0

@juharr你是对的,回答更新... – Ian

+0

@Ian谢谢伊恩。有趣的方法:使用非常基本的LINQ。 –

1

这里是一个LINQ方式:

class Person 
{ 
    public string Name { get; set; } 
    public string Country { get; set; } 
    public string City { get; set; } 
    public string PhoneNumber { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     string[] lines = File.ReadAllLines("data.txt"); 

     List<Person> people = 
      lines 
       .Select((line, index) => 
        new 
        { 
         Index = index/2, 
         RawData = line 
        } 
       ) 
       .GroupBy(obj => obj.Index) 
       .Select(group => 
        { 
         var rawPerson = group.ToArray(); 

         string name = rawPerson[1].RawData; 
         string[] rawDetails = rawPerson[0].RawData.Split('|'); 

         return 
          new Person() 
          { 
           Name = name, 
           City = rawDetails[0], 
           Country = rawDetails[1], 
           PhoneNumber = rawDetails[2] 
          }; 
        } 
       ) 
       .ToList(); 
    } 
} 
+0

谢谢!我很高兴看到同样的事情有很多不同的方法。今天我学到了很多东西:) –