0

Can I reduce the looping in this C# code, perhaps using better LINQ or lambda expressions? I'm essentially looking for a UNION operation that removes duplicates and flags the items that were in both sets.

public class LibraryLocation
{
    public string HoldingType { get; set; }
    public string LibraryLocationName { get; set; }
}

public class HoldingRepo
{
    public HoldingRepo(MyDbContext dbContext)
    {
    }

    public async Task<List<LibraryLocation>> FindLibraryLocationsByLibrary(int libraryId)
    {
        var result = new List<LibraryLocation>();

        var bookHoldings = (from bh in db.BookHoldings
                            where bh.LibraryId == libraryId
                            select bh).Select(x => x.LocationName).Distinct();

        var journalHoldings = (from jh in db.JournalHoldings
                               where jh.LibraryId == libraryId
                               select jh).Select(x => x.LocationName).Distinct();

        // TODO: Improve this by cleaning up three loops below?

        // Add common items
        foreach (var item in await bookHoldings.Intersect(journalHoldings).ToListAsync())
        {
            result.Add(new LibraryLocation { HoldingType = "BOTH", LibraryLocationName = item });
        }

        // Add book items
        foreach (var item in await bookHoldings.Except(journalHoldings).ToListAsync())
        {
            result.Add(new LibraryLocation { HoldingType = "BOOK", LibraryLocationName = item });
        }

        // Add journal items
        foreach (var item in await journalHoldings.Except(bookHoldings).ToListAsync())
        {
            result.Add(new LibraryLocation { HoldingType = "JOURNAL", LibraryLocationName = item });
        }

        return result;
    }
}
jboeke
  • 1,245
  • 10
  • 20
  • If you are looking for union, maybe use Union LINQ function then? Will perform union query to database. – Evk Mar 03 '17 at 22:24
  • _"I'm essentially looking for a UNION operation that removes duplicates and flags the items that were in both sets"_ -- sound like a full outer join to me. You'll get all the rows from both sets, with null values where data is missing. These represent the rows where they are either in only bool or journal collections. See marked duplicate for detailed information on doing that (note...may not be considered simpler than what you have here, but a) can be encapsulated as extension method, and b) can be more efficient than the above if you're using LINQ-to-SQL). – Peter Duniho Mar 03 '17 at 23:58
  • If you think the marked duplicate does not answer your question, post a new question in which you've provided a good [mcve] and explained more precisely what you've already tried, and what specifically you need help with, including why a full outer join _doesn't_ address your need. – Peter Duniho Mar 03 '17 at 23:59
  • Thank you [Peter Duniho](http://stackoverflow.com/users/3538012/peter-duniho)! That got me close enough to what I needed. For future internauts, here is a simplified example of exactly what I needed to do (full outer join into class object): https://gist.github.com/jboeke/b43e2146e3c8d660976971062073be47 – jboeke Mar 04 '17 at 02:11

0 Answers0