How to pick item from another list if my conditions match?

Viewed 227

I have a query regarding C# list.

I have two different types (account and accountDescriptionHistory) of lists. accountID and accountdescription two column present in both the list.

var account = new List<Account>();
var accountDescriptionHistory = new List<AccountDescriptionHistory>();

Now, I want to prepare a result list based on below conditions.

  1. If accountID match, Pick a accountdescription from accountDescriptionHistory list.
  2. Result list should be type of List();

Class definition

public class Account
{

    /// <summary>
    /// The account number
    /// </summary>
    public virtual string AccountNumber { get; set; }

    /// <summary>
    /// The account's description
    /// </summary>
    public virtual string Description { get; set; }
}

Account Description class :

    public class AccountDescriptionHistory : EntityModel<AccountDescriptionHistory>
    {
        #region Public Properties

        /// <summary>
        /// The account description of an account that is valid for a specific date range
        /// </summary>
        public virtual string AccountDescription { get; set; }

        /// <summary>
        /// The account this AccountDescriptionHistory is associated with.
        /// </summary>
        public virtual Account Account { get; set; }
}
4 Answers

Your question is unclear on the exact output. Having said that.

Given

List<Account> accounts = new List<Account>
{ 
    new Account {AccountNumber = "1", Description = "Account 1"}, 
    new Account {AccountNumber = "2", Description = "Account 2"},
    new Account {AccountNumber = "4", Description = "Account 4"}, 
};

List<AccountDescriptionHistory> accountHistories = new List<AccountDescriptionHistory>
{ 
    new AccountDescriptionHistory {AccountDescription = "History Account 1", Account = accounts[0] }, 
    new AccountDescriptionHistory {AccountDescription = "History Account 2", Account = accounts[1] }, 
    new AccountDescriptionHistory {AccountDescription = "History Account 3", Account = new Account {AccountNumber = "3", Description = "Account 3"} }, 
};

And we're wanting to find all the accountHistories that exist in accounts using the AccountNumber, we can write a Where clause to find all this:

List<AccountDescriptionHistory> result = accountHistories
    .Where(x => accounts.Any(y => y.AccountNumber == x.Account.AccountNumber))
    .ToList();

If you're wanting to only retrieve the AccountDescription from the result, you can write:

List<string> result = accountHistories
    .Where(x => accounts.Any(y => y.AccountNumber == x.Account.AccountNumber))
    .Select(x => x.AccountDescription)
    .ToList();

If you're wanting to transform the result into an Account with the description from AccountDescriptionHistory, you can do the following:

List<Account> result = accountHistories
    .Where(x => accounts.Any(y => y.AccountNumber == x.Account.AccountNumber))
    .Select(x => new Account {AccountNumber = x.Account.AccountNumber, Description = x.AccountDescription})
    .ToList();

Edit

You can create a function like this:

static Account WithDescriptionHistory(Account account, IEnumerable<AccountDescriptionHistory> accountHistories)
{
    AccountDescriptionHistory accountHistory = accountHistories.FirstOrDefault(x => x.Account.AccountNumber == account.AccountNumber);
    account.Description = accountHistory?.AccountDescription ?? account.Description;
    return account;
}

Than transform the original account variable like:

accounts = accounts
    .Select(x => WithDescriptionHistory(x, accountHistories))
    .ToList();

Output

History Account 1
History Account 2
Account 4

So base on your comment you need this code

foreach (var a in account)
{
    if (!accountDescriptionHistory.Any(x => x.accountID == a.accountID)) continue;
    a.Description = accountDescriptionHistory.FirstOrDefault(x => x.accountID == a.accountID).AccountDescription;
}

Assuming that you had these two classes:

public class A
{
    public int Id { get; set; }
}

public class B
{
    public int Id { get; set; }
    public string desc { get; set; }
}

You could use the LINQ Join statement to create a list of the descriptions matched to the Id from the first list

    List<A> one = new List<A>
    { 
        new A {Id = 1}, 
        new A {Id = 2} 
    };
    List<B> two = new List<B>
    { 
        new B {Id = 1, desc = "test"}, 
        new B {Id = 2, desc = "test two"} 
    };
    
    var result = one.Join(
        two, 
        x => x.Id, 
        y => y.Id, 
        (x, y) => new {Id = x.Id, Desc = y.desc}
    ).ToList();

Dear Amit I hope this helps

public partial class TesterForm : Form
{
    List<Account> account = new List<Account>();
    List<AccountDescriptionHistory> accountDescriptionHistory = new List<AccountDescriptionHistory>();
    List<AccountDescriptionHistory> resultlist = new List<AccountDescriptionHistory>();

    public TesterForm()
    {
        InitializeComponent();
    }

    public class Account
    {
        public int accountID { get; set; }
        public string accountdescription { get; set; }
    }

    public class AccountDescriptionHistory
    {
        public int accountID { get; set; }
        public string accountdescription { get; set; }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Account accountmodel = new Account();
        accountmodel.accountID = 1;
        accountmodel.accountdescription = "desc1";
        account.Add(accountmodel);
        Account accountmodel1 = new Account();
        accountmodel1.accountID = 2;
        accountmodel1.accountdescription = "desc2";
        account.Add(accountmodel1);
        Account accountmodel3 = new Account();
        accountmodel3.accountID = 3;
        accountmodel3.accountdescription = "desc3";
        account.Add(accountmodel3);

        AccountDescriptionHistory accountdescmodel = new AccountDescriptionHistory();
        accountdescmodel.accountID = 3;
        accountdescmodel.accountdescription = "desc4";
        accountDescriptionHistory.Add(accountdescmodel);
        AccountDescriptionHistory accountdescmodel2 = new AccountDescriptionHistory();
        accountdescmodel2.accountID = 4;
        accountdescmodel2.accountdescription = "desc5";
        accountDescriptionHistory.Add(accountdescmodel2);
        AccountDescriptionHistory accountdescmodel3 = new AccountDescriptionHistory();
        accountdescmodel3.accountID = 5;
        accountdescmodel3.accountdescription = "desc6";
        accountDescriptionHistory.Add(accountdescmodel3);


    }

    private void button2_Click(object sender, EventArgs e)
    {
        foreach (Account item in account)
        {
            foreach (AccountDescriptionHistory item2 in accountDescriptionHistory)
            {
                if (item.accountID==item2.accountID)
                {
                    AccountDescriptionHistory history = new AccountDescriptionHistory();
                    history.accountID = item.accountID;
                    history.accountdescription = item2.accountdescription;
                    resultlist.Add(history);
                }
            }
        }
        comboBox1.DataSource = resultlist;
        comboBox1.DisplayMember = "accountdescription";
    }
}

I am using Visual studio 2019 Forms, you will need two buttons and a combobutton to see the result as i tested it. add to your form combobox1, button1 and button2.

Related