LINQ Как взять одну запись и пропустить rest c#

#c# #linq

#c# #linq

Вопрос:

я попытался взять одну запись и пропустить остальные. мой код не выдает никакой ошибки, но и не выдает никаких выходных данных. вот мой код. поэтому, пожалуйста, взгляните и скажите мне, что не так в моем коде.

 public sealed class Person
{
    public Person() { }
    public Person(string name,bool HQ) {
        this.Name = name;
        this.HQ = HQ;
    }

    private string _Name;
    public string Name
    {
        get { return _Name; }
        set { _Name = value; }
    }

    private bool _HQ;
    public bool HQ
    {
        get { return _HQ; }
        set { _HQ = value; }
    }
}

  protected void btn_Click(object sender, EventArgs e)
    {
        DataTable dt = new DataTable();
        dt.Columns.Add("Name",typeof(string));
        dt.Columns.Add("HQ", typeof(bool));

        DataRow dr = null;
        dr = dt.NewRow();
        dr["Name"]="Arijit";
        dr["HQ"]=true;
        dt.Rows.Add(dr);

        dr = dt.NewRow();
        dr["Name"] = "Dibyendu";
        dr["HQ"] = false;
        dt.Rows.Add(dr);

        dr = dt.NewRow();
        dr["Name"] = "Tridip";
        dr["HQ"] = false;
        dt.Rows.Add(dr);


        List<Person> oPerson1 = (from c in dt.AsEnumerable()
            select new Person
            {
                Name = c.Field<string>("Name"),
                HQ = c.Field<bool>("HQ")
            }).Skip(1).Take(2).ToList();


        List<Person> oPerson2 = (from c in dt.AsEnumerable()
            select new Person
            {
                Name = c.Field<string>("Name"),
                HQ = c.Field<bool>("HQ")
            }).Take(1).Skip(2).ToList();

    }
  

Ответ №1:

если вы хотите взять первую запись, вы можете вызвать эти Take(1) , First() , FirstOrDefault()

если вы хотите взять 1 запись в середине, вызовите это: Skip(n).Take(1) где n — количество пропущенных записей

Когда вы вызываете Take(n) — нет необходимости вызывать Skip после этого, он уже выбрал n записей

Комментарии:

1. Важное различие. Take возвращает IEnumerable<TSource> и First возвращает TSource .

Ответ №2:

Попробуйте этот код.

 Person oPerson1 = (from c in dt.AsEnumerable()
select new Person
{
    Name = c.Field<string>("Name"),
    HQ = c.Field<bool>("HQ")
}).First(); //first person in a list


Person oPerson2 = (from c in dt.AsEnumerable()
select new Person
{
    Name = c.Field<string>("Name"),
    HQ = c.Field<bool>("HQ")
}).Skip(1).First(); //second person in a list

However this code can be rewritten to be clearer:

List<Person> persons = from c in dt.AsEnumerable()
select new Person
{
    Name = c.Field<string>("Name"),
    HQ = c.Field<bool>("HQ")
};

Person oPerson1 = persons[0];
Person oPerson2 = persons[1];
  

Ответ №3:

Я предпочитаю использовать IQueryable , а не List .

В любом случае вы можете использовать Queryable.Пропустите, чтобы пропустить количество элементов, которые вам нужны

    IQueryable<Person> oPerson2 = (from c in dt.AsEnumerable()
            select new Person
            {
                Name = c.Field<string>("Name"),
                HQ = c.Field<bool>("HQ")
            }).Skip(2).Take(1);
  

Также вы найдете больше об этом в Возвращать или пропускать элементы в последовательности (LINQ to SQL)

Ответ №4:

Я не уверен, что вы подразумеваете под «возьмите одну и пропустите остальные», но я подозреваю, что вы путаете, как работают операции LINQ. Они возвращают новую последовательность на основе указанных вами критериев, и эта новая последовательность содержит только то, что вы просили.

Например, если у вас есть список с тремя элементами, и вы вызвали Take(1) , вы получите обратно IEnumerable с 1 элементом. «Пропускать» больше нечего, потому что в вашем списке есть только один элемент. Ваша исходная таблица данных остается неизменной — последовательности LINQ неизменяемы.

Похоже, все, что вы действительно хотите сделать, это:

     List<Person> oPerson2 = (from c in dt.AsEnumerable()
        select new Person
        {
            Name = c.Field<string>("Name"),
            HQ = c.Field<bool>("HQ")
        }).Take(1).ToList();
  

Конечно, это очень распространенная операция в LINQ, поэтому есть другой, несколько «более понятный» способ сделать это:

     Person oPerson2 = (from c in dt.AsEnumerable()
        select new Person
        {
            Name = c.Field<string>("Name"),
            HQ = c.Field<bool>("HQ")
        }).First();
  

Ответ №5:

Если вы хотите получить только одну запись, вам следует заменить вызов final ToList на First() или FirstOrDefault() они здесь как раз для этой цели. Разница между двумя методами заключается в том, First() что они генерируют исключение, если нечего возвращать (например, пустую коллекцию). И FirstOrDefault() вернет default(T) (например, null для классов и 0 для типов значений).

Ответ №6:

Разбивая цепочку, затем:

 List<Person> oPerson2 = (from c in dt.AsEnumerable()
  select new Person
  {
    Name = c.Field<string>("Name"),
    HQ = c.Field<bool>("HQ")
  }).Take(1).Skip(2).ToList();
  

становится:

 var tmp0 = (from c in dt.AsEnumerable()
  select new Person
  {
    Name = c.Field<string>("Name"),
    HQ = c.Field<bool>("HQ")
  });
var tmp1 = tmp0.Take(1);
var tmp2 = tmp1.Skip(2);
List<Person> oPerson2 = tmp2.ToList();
  

Это облегчает обнаружение ошибки. tmp0 — это перечисляемый параметр, который при перечислении вернет все возможные строки. tmp1 — это перечисляемый параметр, который вернет только первую 1 строку в tmp0 (или меньше, если строк недостаточно). tmp2 — это перечисляемый параметр, который пропустит первые 2 строки в tmp1 (или меньше, если строк недостаточно), а затем вернет остальные. Наконец, oPerson2 заставляет эти перечислимые объекты фактически возвращать свои результаты и сохраняет их в списке.

Из этого ясно, что ошибка была .Skip(2) в том, что она использует перечисление из одного элемента, пропускает до 2 и оставляет остальное, в результате чего получается список из max (1 — 2, 0) = 0 элементов.

Не учитывайте Skip() , и вы получите то, что хотите, поскольку «взять до 1» уже влечет за собой «пропустить остальное».

Ответ №7:

Также .Для достижения этого можно использовать First()

 List<X> xlist= XBusiness.GetAllX(xname.ToString());
X lastX = xlist.First();