Kingshuk_SP Ответов: 2

Фильтр данных по фамилии в столбце имя


У меня есть Datatable как

Name                ID
Kingshuk Dutta      2
Tapas Nayak         4
Prakash Kiran       7


Я должен отсортировать datatable по столбцу Name, но только по фамилии.
Это должно быть похоже на:

Name                ID
Kingshuk Dutta      2
Prakash Kiran       7
Tapas Nayak         4


Что я уже пробовал:

Объект DataTable возвращается такой, я к нему.

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

2 Ответов

Рейтинг:
7

Thomas Daniels

Решение 1 обеспечивает самый простой способ сделать это. Однако если вам действительно нужно иметь одно поле имени, есть способ его сортировки:

dt.AsEnumerable().OrderBy(x => (x.ItemArray[0] as string).Split(' ')[1]).CopyToDataTable(); // where 'dt' is your DataTable

AsEnumerable возвращает EnumerableRowCollection<DataRow>, по которому вы можете позвонить OrderBy с лямбда-выражением, которое говорит использовать второе слово имени. Это возвращает OrderedEnumerableRowCollection<DataRow> и вы можете позвонить CopyToDataTable чтобы преобразовать эту коллекцию в новую DataTable.


Karthik_Mahalingam

5

Kingshuk_SP

один вопрос.

can you explain the use of "Split(' ')[1]" in the query please ???

Kingshuk_SP

да, я получил это для первого места, мы получим фамилию и сортировку. хорошо.

Но если имя столбца, как:

Мэри Сью Ван Пелт
Роза Ван Джульетта

в таком случае, как я могу запустить цикл ?

Thomas Daniels

Что вы здесь считаете "фамилией"? Только последняя часть? Или все, кроме первой части?

Kingshuk_SP

yeah only last part. 

like in case of the below name:

Mary Sue Van Pelt

"Pelt" would be the last name

Kingshuk_SP

спасибо, ребята. Я нашел решение:

код будет таким:

dt = dt.AsEnumerable().OrderBy(x => (x.ItemArray[0] as string).Split(' ')[(x.ItemArray[0]).ToString().Split(' ').Length - 1]).CopyToDataTable();

Thomas Daniels

Если вы используете LINQ (using System.Linq;), вы также можете использовать .Last метод расширения для облегчения чтения вашего кода:

.Split(' ').Last()

Kingshuk_SP

спасибо @ProgramFOX

это уменьшило мой код... ура. :)

Thomas Daniels

Пожалуйста!

Kingshuk_SP

мне нужно еще кое-что. У меня есть datatable, как показано ниже:

Name               Department
John Alter         D01
Prakash Kiran      D01
Steffy Cold        D01
Julia Roberts      D02
Candy Mitchel      D02
Monika Diesel      D03


Я хочу, чтобы это было как ниже:

Name               Department
John Alter         D01
Prakash Kiran      
Steffy Cold        
Julia Roberts      D02
Candy Mitchel      
Monika Diesel      D03


когда его заказывает отдел, он не должен повторяться для одного и того же отдела.
Но строка должна быть там, только если в следующей строке под столбцом отдела есть такое же значение, которое должно быть пустым

Thomas Daniels

Для этого нет однострочного решения, но это работает (Примечание: чтобы это сработало, DataTable уже должен быть отсортирован)

DataTable newDt = dt.Clone(); // clones the structure, not the data
for (int i = 0; i < dt.Rows.Count; i++)
{
    DataRow newRow = newDt.NewRow();
    newRow["Name"] = dt.Rows[i]["Name"];
    int originalIndex = dt.AsEnumerable().ToList().FindIndex(x => x["Department"] == dt.Rows[i]["Department"]);
    if (originalIndex < i)
    {
        newRow["Department"] = "";
    }
    else
    {
        newRow["Department"] = dt.Rows[i]["Department"];
    }
    newDt.Rows.Add(newRow);
}

Kingshuk_SP

in this case the condition if (originalIndex < i) always is false and thus not removing the duplicate names.

i think we should go for a counter or flag concept

Kingshuk_SP

in this case the condition if (originalIndex < i) always is false and thus not removing the duplicate names.

Thomas Daniels

Для меня это сработало. originalIndex - это первое вхождение определенного отдела, поэтому "originalIndex < i" будет истинным, если имя отдела будет использовано позже.

Kingshuk_SP

для меня это не работает, потому что всегда значение originalIndex равно значению i.
Я отладил и все равно его же. :(

Thomas Daniels

Тогда, боюсь, я ничем не могу помочь.

Kingshuk_SP

ok. but when I am debugging , i saw...

every time the loop runs, as the "i" value increments, the originalIndex value also increments.. always their value is same. that's y its not going to be true anytime.

int originalIndex = dt.AsEnumerable().ToList().FindIndex(x => x["Department"] == dt.Rows[i]["Department"]);

here originalIndex value is dependent on "i" everytime
so it will find the index of that row according to i value right.

so as an example, when i == 0 , then it will find the index of department corresponds to 0th row and so on....

then how it is coming different in your case, I am not getting really. :)

if you don't mind can you please re-check if you have made any small code changes inside this please

Thomas Daniels

dt.Rows[i]["Department"] просто возвращает отдел строки, которую вы копируете в newDt, так что это будет "D01" как для первой, так и для второй строки.

Это прекрасно работает для меня; единственное, что я вижу, что можно было бы изменить, - это замена '==' в этой строке на вызов. Equals:

int originalIndex = dt.AsEnumerable().ToList().FindIndex(x => x["Department"].Equals(dt.Rows[i]["Department"]));

Kingshuk_SP

Большое спасибо. Это делается с помощью Equal. овации. :)

Рейтинг:
2

Graeme_Grant

Если вы разделите имя и фамилию на отдельные столбцы, это значительно облегчит работу с вашими данными.