Parse string and order by parsed value

592 Views Asked by At

i am trying to build linq expression to solve my problem. I have list of strings

List<string> arr = new List<string>();
arr.Add("<desc><ru>1</ru><en>3</en></desc>");
arr.Add("<desc><ru>2</ru><en>4</en></desc>");

i want to parse every item and order results

fake sample:
arr.Select(ParseItem("en")).OrderBy(x) 

then we have two items in ru in order 1,2

Thanks for all and sorry for my bad English Thanks for all response but how to convert now results to IQueryable

class Test { public string data { get; set; } } 
List<Test> arr = new List<Test>();

arr.Add(new Test { data = "<desc><ru>AAA</ru><en>One</en></desc>" });
arr.Add(new Test { data = "<desc><ru>1</ru><en>Two</en></desc>" });
arr.Add(new Test { data = "<desc><ru>22</ru><en>Ab</en></desc>" });
IQueryable<Test> t = arr.AsQueryable();

// here the trouble how to convert to IQueryable<Test>
t = t.Select(s => XElement.Parse(s.data)).Select(x => x.Element("en")).
OrderBy(el => el.Value);

Thanks again

4

There are 4 best solutions below

1
On BEST ANSWER

After the question update - this will return your ordered data by <en> node value:

var result = arr
    .OrderBy(t=>
        XElement.Parse(t.data).Element("en").Value
    );

The result valiable is of IOrderedEnumerable<Test> type.

0
On

This will produce a list of the values in ru tags (assuming they are integers), ordered by the values in en tags (again, assuming integers).

List<string> items = arr.Select(s => XElement.Parse(s))
                        .OrderBy(xml => (int)xml.Element("en"))
                        .Select(xml => (int)xml.Element("ru"))
                        .ToList();

If you simply want to enumerate, you can omit the ToList call:

foreach (var item in arr.Select(s => XElement.Parse(s))
                        .OrderBy(xml => (int)xml.Element("en"))
                        .Select(xml => (int)xml.Element("ru")))
{
    // do something with item
}
0
On

I'm not sure I've got what the excepted results are, but if you need to select values in en ordered by the value in ru then here it is:

var orderedItems = (
    from item in arr
    let x = XElement.Parse(item)
    let ruValue = (int)x.Element("ru")
    let enValue = (int)x.Element("en")
    orderby ruValue
    select enValue
    ).ToList();
0
On

I don't know if it is too late, but if you are wanting to parse the text and if it is an integer then sort by value otherwise sort by text, then this might help.

You need to define a function like this to enable parsing in LINQ expressions:

Func<string, int?> tryParseInteger = text =>
{
    int? result = null;
    int parsed;
    if (int.TryParse(text, out parsed))
    {
        result = parsed;
    }
    return result;
};

Then you can do queries like this:

var xs = new [] { "Hello", "3ff", "4.5", "5", };
var rs =
    (from x in xs
     select tryParseInteger(x)).ToArray();
// rs == new int?[] { null, null, null, 5, };

In your case you possibly want something like this:

var elements = new []
{
    "<desc><ru>AAA</ru></desc>",
    "<desc><ru>1</ru></desc>",
    "<desc><ru>42</ru></desc>",
    "<desc><ru>-7</ru></desc>",
    "<desc><ru>BBB</ru></desc>",
    "<desc><ru>22</ru></desc>",
};

var query =
    from e in elements
    let xe = XElement.Parse(e)
    let v = xe.Element("ru").Value
    orderby v
    orderby tryParseInteger(v)
    select v;

Which would give you:

{ "AAA", "BBB", "-7", "1", "22", "42" }

If you want to treat non-integers (ie parsed as null) to be zero then change the query by using this line:

    orderby tryParseInteger(v) ?? 0

Then you'll get this:

{ "-7", "AAA", "BBB", "1", "22", "42" }

I hope this helps.