Govind
Govind

Reputation: 979

Linq check value for equality in collection and assign value to other collection

I have model called Message and History. History has another model namely List

Message model has property as below,

MessageId,Title,Content,FileID,FileName 

History Model:

Title,Content,List<File> 

File Model:----this is list in History model

FileId,FileName

MessageModel Data as below, MessageId Title Content FileId FileName 101

MessageId  Title    Content   Fileid FileName  
100      1st title  1st content 1    User.pdf  
100      1st title  1st content 2    Log.txt  
100      1st title  1st content 3    manual.doc  
101      2nd title  2nd content 4    dummy.txt   
102      3rd title  3rd content Null     Null  
103      4th title  4th content Null     Null  

Scenario: single messageid can have more than 1 fileid,filename or no fileid,filename.

I want to assign distinct value of message title,content to History model Title and Content and Fileid,FileName to File Model List

My History model should have values like below,

Title     Content       Fileid  FileName
1st title   1st content    1     User.pdf
                            2    Log.txt
                            3    manual.doc
2nd title   2nd content    4     dummy.txt
3rd title   3rd content   Null   Null
4th title   4th content   Null   Null

Messageid is unique here. I learnt to write simple query in linq. For the above scenario can anyone suggest how to do.

Upvotes: 1

Views: 85

Answers (2)

petelids
petelids

Reputation: 12815

You can use GroupBy.

Assuming messages is an IEnumerable the following should do what you're after:

var history = messages.GroupBy(m => new { m.Title, m.Content }, (group, data) => new HistoryModel()
{
    Title = group.Title,
    Content = group.Content,
    Files = data.Select(k => new File() 
                                { 
                                    FileId = k.Fileid, 
                                    FileName = k.FileName
                                }
                        ).ToList(),
});

This basically says to group the messages by their Title and Content properties. For each group the lambda is called passing in group which is an anonymous type containing the details of the group (namely the Title and Content) and data which is an IEnumerable<MessageModel> containing each MessageModel in the group. From that we can construct a list of HistoryModel.

Edit after OPs question

The above should only give you 4 elements in history. The full listing I've used to test this is:

class MessageModel
{
    public string MessageId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public string Fileid { get; set; }
    public string FileName { get; set; }

    public MessageModel(string m, string t, string c, string f, string f2)
    {
        MessageId = m;
        Title = t;
        Content = c;
        Fileid = f;
        FileName = f2;
    }
}

class HistoryModel
{
    public string Title { get; set; }
    public string Content { get; set; }
    public List<File> Files { get; set; }
}

class File
{
    public string FileId { get; set; }
    public string FileName { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        List<MessageModel> messages = new List<MessageModel>();
        messages.Add(new MessageModel("100", "1st title", "1st content", "1", "User.pdf"));
        messages.Add(new MessageModel("100", "1st title", "1st content", "2", "Log.txt"));
        messages.Add(new MessageModel("100", "1st title", "1st content", "3", "manual.doc"));
        messages.Add(new MessageModel("101", "2nd title", "2nd content", "4", "dummy.txt"));
        messages.Add(new MessageModel("102", "3rd title", "3rd content", null, null));
        messages.Add(new MessageModel("103", "4th title", "4th content", null, null));

        var history = messages.GroupBy(m => new { m.Title, m.Content }, (group, data) => new HistoryModel()
        {
            Title = group.Title,
            Content = group.Content,
            Files = data.Select(k => new File()
            {
                FileId = k.Fileid,
                FileName = k.FileName
            }).ToList(),
        });

        foreach (var h in history)
        {
            Console.WriteLine(h.Title + " " + h.Content);

            foreach (var file in h.Files)
            {
                Console.WriteLine("\t" + file.FileId + " " + file.FileName);
            }
        }

        Console.ReadLine();
    }

}

The above produces the output:

1st title 1st content
    1 User.pdf
    2 Log.txt
    3 manual.doc
2nd title 2nd content
    4 dummy.txt
3rd title 3rd content

4th title 4th content

Upvotes: 1

TYY
TYY

Reputation: 2716

You can use a Group by clause to group the common Properties (MessageId, Title and Content). Then using that as the ke you can then use the Select clause to build the HistoryModel.

Full example below (note the .Dump() is from LinqPad)

void Main()
{
    var messages = new List<MessageModel>
    {
        new MessageModel(100,"1st title","1st content", 1,"User.pdf"),
        new MessageModel(100,"1st title","1st content",  2,"Log.txt"),
        new MessageModel(100,"1st title","1st content", 3,"manual.doc"),
        new MessageModel(101,"2nd title","2nd content", 4,"dummy.txt"),   
        new MessageModel(102,"3rd title","3rd content" ),
        new MessageModel(103,"3rd title","3rd content")
    };

    var groupedMessages = 
    messages.GroupBy(x=> new {x.MessageId, x.Title, x.Content})
            .Select(x=> new HistoryModel
                          {
                            MessageId =  x.Key.MessageId,
                            Title = x.Key.Title,
                            Content = x.Key.Content,
                            Files = new List<FileModel>(x.Where( f=>  f.FileId != null)
                                                         .Select( g => new FileModel(g.FileId,  g.FileName)))
                          });

    groupedMessages.Dump();
}

// Define other methods and classes here
public class MessageModel
{
    public int MessageId {get; set;}

    public string Title {get; set;}

    public string Content {get; set;}

    public int? FileId {get; set;}

    public string FileName {get; set;}

    public MessageModel(int id, string title, string content, int? fileId = null, string fileName= null)
    {
        MessageId = id;
        Title =  title;
        Content = content;
        FileId = fileId;
        FileName = fileName;
    }
}

public class HistoryModel
{
    public int MessageId {get; set;}

    public string Title {get; set;}

    public string Content {get; set;}

    public List<FileModel> Files{get; set;} = new List<FileModel>();

}

public class FileModel
{
    public int? FileId {get; set;}

    public string FileName {get; set;}

    public FileModel(int? id, string name)
    {
        FileId = id;
        FileName = name;
    }
}

Upvotes: 1

Related Questions