DataTable Linq 질문 합니다!

안녕하세요

DataTable 형식으로 Linq 메서드 기반으로 데이터를 추출하는데 어려움이 생겨 질문을 올립니다.

Id value
1 text
2 text1|test2

해당처럼 데이터가 있을경우 Id =2 의 value 값을 ‘|’ Split 해서 따로따로 데이터를 얻고자합니다.

원하는 형식은
Id value
1 text
2 text1
2 text2

해당 처럼 얻고자 하는데 linq 메서드 구문으로 어떻게 추출해서 DataTable 형식 또는 Array 형식으로 받을 수 있을까요?

좋아요 3

Select 이용하시면 될 것 같습니다.

.Select(x => x.Split(’|’));

이런형식이 되겠죠? 그러면 return형은 IEnumerable<string[]> 이 될 것 같습니다.

원하시는 바랑 완벽히 일치하지는 않지만 한 번의 Linq로는 원하시는 결과는 못 얻으실 것 같습니다.

좋아요 3

일단 DataTable 대상을 LINQ로 질의하는 방법은 구글링에 많이 나오니 그걸 여쭤보신 건 아닌것 같고, @Vincent 님의 방식에서 좀 더 보완은 아래의 코드를 확인하면 됩니다.

(record는 비슷하게 구성하기 위한 용도로 사용한 것으로 무시해도 됩니다.)

using System.Linq;

var list = new Data[]
{
    new(1, "text"),
    new(2, "text1|text2")
};

var result = list.SelectMany(x => x.Text.Split('|').Select(y => new Data(x.Id, y)));

foreach (var item in result)
    Console.WriteLine(item);

record Data(int Id, string Text);

| 결과

Data { Id = 1, Text = text }
Data { Id = 2, Text = text1 }
Data { Id = 2, Text = text2 }

DataTable에서 위와같이 사용하려면 Field<T>()을 이용해 각 컬럼 값을 가져오고, Data대신 익명 클래스튜플로 반환하면 될 것 같네요.

좋아요 6

Code 1

using System;
using System.Data;
using System.Linq;

var dt = new DataTable();
var idColumn = new DataColumn("id", typeof(int));
var valueColumn = new DataColumn("value", typeof(string));

dt.Columns.Add(idColumn);
dt.Columns.Add(valueColumn);

dt.Rows.Add(1, "text");
dt.Rows.Add(2, "text1|test2");
dt.Rows.Add(3, "text1|test2|text3");

foreach (var row in dt.Rows.Cast<DataRow>().ToArray())
{
    var id = row.Field<int>("id");
    var value = row.Field<string>("value");

    foreach (var v in value.Split('|'))
    {
        dt.Rows.Add(id, v);
    }

    row.Delete();
}

foreach (DataRow row in dt.Rows)
{
    foreach (DataColumn column in dt.Columns)
    {
        Console.Write($"{row[column]} ");
    }

    Console.WriteLine();
}

결과 :

1 text
2 text1
2 test2
3 text1
3 test2
3 text3

Code 2

using System;
using System.Data;
using System.Linq;

var dt = new DataTable();
var idColumn = new DataColumn("id", typeof(int));
var valueColumn = new DataColumn("value", typeof(string));

dt.Columns.Add(idColumn);
dt.Columns.Add(valueColumn);

dt.Rows.Add(1, "text");
dt.Rows.Add(2, "text1|test2");
dt.Rows.Add(3, "text1|test2|text3");

var result = dt.AsEnumerable().SelectMany(r => r.Field<string>("value")
    .Split('|')
    .Select(x => new
    {
        id = r.Field<int>("id"),
        value = x
    })
).ToArray();

foreach (var pair in result)
{
    Console.WriteLine($"{pair.id} {pair.value}");
}

결과 :

1 text
2 text1
2 test2
3 text1
3 test2
3 text3
좋아요 4

저는 SelectMany 가 머리에 한 방에 잘 안 들어와서

var query = list.SelectMany(
		record => record.Text.Split(new string[]{"|"}, StringSplitOptions.None),
		(record, split) => new Data(record.Id, split));

요래요래 쪼개서 썼는데,

요거 깔끔하군요! >ㅁ<b

좋아요 6