Getting latest version in a table and putting them into a list

Viewed 70

I've been at this for days and i still can't find a linq query that works. can anyone help me with a query on how to get the latest version of a item and put them into a list. The data structure looks like this

name  | version
 john |    1.2.35
 john |    1.3
 karen|    2.0
 sora |    1.1.36

output should be

name  | version
 john |    1.3
 karen|    2.0
 sora |    1.1.36

so far i have this code

var packages = _readOnlyContext.Names.AsEnumerable().Select(x => new Names
            {
                Name = x.Name,
                Version = x.Version.ToString()
            });
6 Answers

Used some part of the code from Jonathan, for the testing purpose.

You can use Version.TryParse Method and this extension method for LINQ queries:

and this extension method for LINQ queries:

public class NameVersion
    {
        public string Name { get; set; }
        public string Version { get; set; }

        public NameVersion(string name, string version)
        {
            Name = name;
            Version = version;
        }
    }

    public static class Program
    {

        public static Version TryGetVersion(this string item)
        {
            Version ver;
            bool success = Version.TryParse(item, out ver);
            if (success) return ver;
            return null;
        }

        static void Main(string[] args)
        {

            var theList = new List<NameVersion>{
            new NameVersion("john", "1.2.35"),
            new NameVersion("john", "1.3"),
            new NameVersion("karen", "2.0"),
            new NameVersion("sora ", "1.1.36")
        };

            var sortedVData = theList.AsEnumerable()
            .Select(v => new { Obj = v, Version = v.Version.TryGetVersion() })
            .OrderBy(x => x.Version)
            .Select(x => x.Obj).ToList();
        }
 
    }

Fiddle : https://dotnetfiddle.net/SK2bqy

You will have to GroupBy on name, and then sort descending on version. Something like:

using System;
using System.Collections.Generic;
using System.Linq;
                    
public class Program
{
    public static void Main()
    {
        var theList = new List<NameVersion>{
            new NameVersion("john", "1.2.35"),
            new NameVersion("john", "1.3"),
            new NameVersion("karen", "2.0"),
            new NameVersion("sora ", "1.1.36")
        };
        
        var latestVersion = theList.GroupBy(i => i.Name)
            .Select(i => new{
                Name = i.Key,
                Version = i.OrderByDescending(j => j.Version).FirstOrDefault().Version
            });
        
        foreach(var nv in latestVersion){
            Console.WriteLine($"name: {nv.Name} version: {nv.Version}");
        }
        
    }
}

public class NameVersion
{
    public string Name {get;set;}
    public string Version {get;set;}
    
    public NameVersion(string name, string version){
        Name = name;
        Version = version;
    }
}

See: https://dotnetfiddle.net/yMtAhx

Output:

name: john version: 1.3

name: karen version: 2.0

name: sora version: 1.1.36

public class MyClass
    {
      public string Name { get; set; }
      public string Version { get; set; }
    }

var list = new List<MyClass>()
        {
            new MyClass{Name="John",Version="1.2.35"},
            new MyClass{Name="John",Version="1.3"},
            new MyClass{Name="Karen",Version="2.0"},
            new MyClass{Name="Karen",Version="1.1.37"},
            new MyClass{Name="Sora",Version="1.1.36"},
        };
  
var newList = list.Select(
            x => new
            {
                x.Name,
                Version = Version.Parse(x.Version)
            }).GroupBy(x => x.Name, (a, b) => b.OrderByDescending(y => y.Version).First().ToString()).ToList();
 

The result is:

enter image description here

try this

var result= _readOnlyContext.Names.GroupBy(l => l.Name)
.Select(g => g.OrderByDescending(c => c.Version).FirstOrDefault())
.ToList();

or if you have a lot of properties, but need only 2

var result= _readOnlyContext.Names
.Select(x =>  new {
        Name = x.Name,
         Version = x.Version.ToString()
        })
.GroupBy(l => l.Name)
.Select(g => g.OrderByDescending(c => c.Version).FirstOrDefault())
.ToList();

just use GroupBy and OrderByDescending :

var packages = _readOnlyContext.Names.AsEnumerable()
    .OrderByDescending(o=> o.Version)
    .GroupBy(x=> x.Name)
    .Select(x=>
            new Names
            {
                Name = x.Key,
                Version = x.FirstOrDefault(c=> c.Name == x.Key)?.Version.ToString()                         
            }).ToList();    

You can try this

var result = _readOnlyContext.Names
            .GroupBy(s => s.Name)
            .Select(g => new
            {
                Name = g.Key,
                Version = g.Select(s => s.Version).Max()
            }).ToList();
Related