Remove items earlier than a fix date and replace the first occurrence












0















Based on a list of a typed class like



class CostCenter
{
string center;
string percentage;
DateTime start;
}


I have a list of these elements like this:




  • {"a", 70, "2019/11/10"}

  • {"b", 30, "2019/11/10"}

  • {"A", 40, "2018/10/05"}

  • {"B", 60, "2018/10/05"}

  • {"xx", 10, "2010/01/01"}

  • {"yy", 90, "2010/01/01"}

  • {"100", 50, "2009/07/03"}

  • {"101", 50, "2009/07/03"}


taking into account that I want to get rid of all of the elements (list) that have a start date earlier or equal than a fixed(_earliestDate), also this fixed data will replace the earliest match. In this example the earliest date is "2010/11/01", therefore "xx" and "yy" start date is replaced to "2010/11/01".
The output should be like this:




  • {"a", 70, "2019/11/10"}

  • {"b", 30, "2019/11/10"}

  • {"A", 40, "2018/10/05"}

  • {"B", 60, "2018/10/05"}

  • {"xx", 10, "2010/11/01"}

  • {"yy", 90, "2010/11/01"}


I have created the following code:



string dateToReplace = null;
bool earliestFound = false;
foreach (var item in list.OrderByDescending(x => DateTime.Parse(x.start)).ToList())
{
if (earliestFound) //already marked, safe to remove others
{
list.Remove(item);
continue;
}

if (!string.IsNullOrEmpty(dateToReplace)) //remaining matches
{
if (string.Equals(item.start, dateToReplace))
{
item.start = _earliestDate;
continue;
}
else
{
earliestFound = true;
list.Remove(item);
continue;
}
}
if (item.start <= _earliestDate) //first earliest or same, more required
{
dateToReplace = item.start;
item.start = _earliestDate;
}
}


dateToReplace and earliestFound will be used as flags in the code to determine when to loop.



Somehow I think it is not the best option, do you have any suggestion on how to make it easier to understand or efficient?










share|improve this question

























  • Does your code works without exception? Usually, it is not allowed to alter a list, while iterating over it at the same time... Regarding your question: a different approach may be the linq Where() method to only fetch the items from the list that should be removed or updated.

    – Nicolas
    Nov 26 '18 at 13:45













  • Wow, it looks like a very complicated way to do something very simple. At the same time, I didn't understand what you are trying to achieve.

    – Yeldar Kurmangaliyev
    Nov 26 '18 at 13:45






  • 1





    @YeldarKurmangaliyev this seem to be a cleanup of a history alike list

    – Nicolas
    Nov 26 '18 at 13:46











  • @DanielV, Instead of removing items from list, can we create new list with filtered results? If Yes then we can do it in one line

    – Prasad Telkikar
    Nov 26 '18 at 13:52








  • 1





    @PrasadTelkikar yes, there is no restriction to remove items from the list

    – DanielV
    Nov 26 '18 at 13:55
















0















Based on a list of a typed class like



class CostCenter
{
string center;
string percentage;
DateTime start;
}


I have a list of these elements like this:




  • {"a", 70, "2019/11/10"}

  • {"b", 30, "2019/11/10"}

  • {"A", 40, "2018/10/05"}

  • {"B", 60, "2018/10/05"}

  • {"xx", 10, "2010/01/01"}

  • {"yy", 90, "2010/01/01"}

  • {"100", 50, "2009/07/03"}

  • {"101", 50, "2009/07/03"}


taking into account that I want to get rid of all of the elements (list) that have a start date earlier or equal than a fixed(_earliestDate), also this fixed data will replace the earliest match. In this example the earliest date is "2010/11/01", therefore "xx" and "yy" start date is replaced to "2010/11/01".
The output should be like this:




  • {"a", 70, "2019/11/10"}

  • {"b", 30, "2019/11/10"}

  • {"A", 40, "2018/10/05"}

  • {"B", 60, "2018/10/05"}

  • {"xx", 10, "2010/11/01"}

  • {"yy", 90, "2010/11/01"}


I have created the following code:



string dateToReplace = null;
bool earliestFound = false;
foreach (var item in list.OrderByDescending(x => DateTime.Parse(x.start)).ToList())
{
if (earliestFound) //already marked, safe to remove others
{
list.Remove(item);
continue;
}

if (!string.IsNullOrEmpty(dateToReplace)) //remaining matches
{
if (string.Equals(item.start, dateToReplace))
{
item.start = _earliestDate;
continue;
}
else
{
earliestFound = true;
list.Remove(item);
continue;
}
}
if (item.start <= _earliestDate) //first earliest or same, more required
{
dateToReplace = item.start;
item.start = _earliestDate;
}
}


dateToReplace and earliestFound will be used as flags in the code to determine when to loop.



Somehow I think it is not the best option, do you have any suggestion on how to make it easier to understand or efficient?










share|improve this question

























  • Does your code works without exception? Usually, it is not allowed to alter a list, while iterating over it at the same time... Regarding your question: a different approach may be the linq Where() method to only fetch the items from the list that should be removed or updated.

    – Nicolas
    Nov 26 '18 at 13:45













  • Wow, it looks like a very complicated way to do something very simple. At the same time, I didn't understand what you are trying to achieve.

    – Yeldar Kurmangaliyev
    Nov 26 '18 at 13:45






  • 1





    @YeldarKurmangaliyev this seem to be a cleanup of a history alike list

    – Nicolas
    Nov 26 '18 at 13:46











  • @DanielV, Instead of removing items from list, can we create new list with filtered results? If Yes then we can do it in one line

    – Prasad Telkikar
    Nov 26 '18 at 13:52








  • 1





    @PrasadTelkikar yes, there is no restriction to remove items from the list

    – DanielV
    Nov 26 '18 at 13:55














0












0








0








Based on a list of a typed class like



class CostCenter
{
string center;
string percentage;
DateTime start;
}


I have a list of these elements like this:




  • {"a", 70, "2019/11/10"}

  • {"b", 30, "2019/11/10"}

  • {"A", 40, "2018/10/05"}

  • {"B", 60, "2018/10/05"}

  • {"xx", 10, "2010/01/01"}

  • {"yy", 90, "2010/01/01"}

  • {"100", 50, "2009/07/03"}

  • {"101", 50, "2009/07/03"}


taking into account that I want to get rid of all of the elements (list) that have a start date earlier or equal than a fixed(_earliestDate), also this fixed data will replace the earliest match. In this example the earliest date is "2010/11/01", therefore "xx" and "yy" start date is replaced to "2010/11/01".
The output should be like this:




  • {"a", 70, "2019/11/10"}

  • {"b", 30, "2019/11/10"}

  • {"A", 40, "2018/10/05"}

  • {"B", 60, "2018/10/05"}

  • {"xx", 10, "2010/11/01"}

  • {"yy", 90, "2010/11/01"}


I have created the following code:



string dateToReplace = null;
bool earliestFound = false;
foreach (var item in list.OrderByDescending(x => DateTime.Parse(x.start)).ToList())
{
if (earliestFound) //already marked, safe to remove others
{
list.Remove(item);
continue;
}

if (!string.IsNullOrEmpty(dateToReplace)) //remaining matches
{
if (string.Equals(item.start, dateToReplace))
{
item.start = _earliestDate;
continue;
}
else
{
earliestFound = true;
list.Remove(item);
continue;
}
}
if (item.start <= _earliestDate) //first earliest or same, more required
{
dateToReplace = item.start;
item.start = _earliestDate;
}
}


dateToReplace and earliestFound will be used as flags in the code to determine when to loop.



Somehow I think it is not the best option, do you have any suggestion on how to make it easier to understand or efficient?










share|improve this question
















Based on a list of a typed class like



class CostCenter
{
string center;
string percentage;
DateTime start;
}


I have a list of these elements like this:




  • {"a", 70, "2019/11/10"}

  • {"b", 30, "2019/11/10"}

  • {"A", 40, "2018/10/05"}

  • {"B", 60, "2018/10/05"}

  • {"xx", 10, "2010/01/01"}

  • {"yy", 90, "2010/01/01"}

  • {"100", 50, "2009/07/03"}

  • {"101", 50, "2009/07/03"}


taking into account that I want to get rid of all of the elements (list) that have a start date earlier or equal than a fixed(_earliestDate), also this fixed data will replace the earliest match. In this example the earliest date is "2010/11/01", therefore "xx" and "yy" start date is replaced to "2010/11/01".
The output should be like this:




  • {"a", 70, "2019/11/10"}

  • {"b", 30, "2019/11/10"}

  • {"A", 40, "2018/10/05"}

  • {"B", 60, "2018/10/05"}

  • {"xx", 10, "2010/11/01"}

  • {"yy", 90, "2010/11/01"}


I have created the following code:



string dateToReplace = null;
bool earliestFound = false;
foreach (var item in list.OrderByDescending(x => DateTime.Parse(x.start)).ToList())
{
if (earliestFound) //already marked, safe to remove others
{
list.Remove(item);
continue;
}

if (!string.IsNullOrEmpty(dateToReplace)) //remaining matches
{
if (string.Equals(item.start, dateToReplace))
{
item.start = _earliestDate;
continue;
}
else
{
earliestFound = true;
list.Remove(item);
continue;
}
}
if (item.start <= _earliestDate) //first earliest or same, more required
{
dateToReplace = item.start;
item.start = _earliestDate;
}
}


dateToReplace and earliestFound will be used as flags in the code to determine when to loop.



Somehow I think it is not the best option, do you have any suggestion on how to make it easier to understand or efficient?







c#






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 26 '18 at 14:59







DanielV

















asked Nov 26 '18 at 13:37









DanielVDanielV

78211741




78211741













  • Does your code works without exception? Usually, it is not allowed to alter a list, while iterating over it at the same time... Regarding your question: a different approach may be the linq Where() method to only fetch the items from the list that should be removed or updated.

    – Nicolas
    Nov 26 '18 at 13:45













  • Wow, it looks like a very complicated way to do something very simple. At the same time, I didn't understand what you are trying to achieve.

    – Yeldar Kurmangaliyev
    Nov 26 '18 at 13:45






  • 1





    @YeldarKurmangaliyev this seem to be a cleanup of a history alike list

    – Nicolas
    Nov 26 '18 at 13:46











  • @DanielV, Instead of removing items from list, can we create new list with filtered results? If Yes then we can do it in one line

    – Prasad Telkikar
    Nov 26 '18 at 13:52








  • 1





    @PrasadTelkikar yes, there is no restriction to remove items from the list

    – DanielV
    Nov 26 '18 at 13:55



















  • Does your code works without exception? Usually, it is not allowed to alter a list, while iterating over it at the same time... Regarding your question: a different approach may be the linq Where() method to only fetch the items from the list that should be removed or updated.

    – Nicolas
    Nov 26 '18 at 13:45













  • Wow, it looks like a very complicated way to do something very simple. At the same time, I didn't understand what you are trying to achieve.

    – Yeldar Kurmangaliyev
    Nov 26 '18 at 13:45






  • 1





    @YeldarKurmangaliyev this seem to be a cleanup of a history alike list

    – Nicolas
    Nov 26 '18 at 13:46











  • @DanielV, Instead of removing items from list, can we create new list with filtered results? If Yes then we can do it in one line

    – Prasad Telkikar
    Nov 26 '18 at 13:52








  • 1





    @PrasadTelkikar yes, there is no restriction to remove items from the list

    – DanielV
    Nov 26 '18 at 13:55

















Does your code works without exception? Usually, it is not allowed to alter a list, while iterating over it at the same time... Regarding your question: a different approach may be the linq Where() method to only fetch the items from the list that should be removed or updated.

– Nicolas
Nov 26 '18 at 13:45







Does your code works without exception? Usually, it is not allowed to alter a list, while iterating over it at the same time... Regarding your question: a different approach may be the linq Where() method to only fetch the items from the list that should be removed or updated.

– Nicolas
Nov 26 '18 at 13:45















Wow, it looks like a very complicated way to do something very simple. At the same time, I didn't understand what you are trying to achieve.

– Yeldar Kurmangaliyev
Nov 26 '18 at 13:45





Wow, it looks like a very complicated way to do something very simple. At the same time, I didn't understand what you are trying to achieve.

– Yeldar Kurmangaliyev
Nov 26 '18 at 13:45




1




1





@YeldarKurmangaliyev this seem to be a cleanup of a history alike list

– Nicolas
Nov 26 '18 at 13:46





@YeldarKurmangaliyev this seem to be a cleanup of a history alike list

– Nicolas
Nov 26 '18 at 13:46













@DanielV, Instead of removing items from list, can we create new list with filtered results? If Yes then we can do it in one line

– Prasad Telkikar
Nov 26 '18 at 13:52







@DanielV, Instead of removing items from list, can we create new list with filtered results? If Yes then we can do it in one line

– Prasad Telkikar
Nov 26 '18 at 13:52






1




1





@PrasadTelkikar yes, there is no restriction to remove items from the list

– DanielV
Nov 26 '18 at 13:55





@PrasadTelkikar yes, there is no restriction to remove items from the list

– DanielV
Nov 26 '18 at 13:55












5 Answers
5






active

oldest

votes


















4














To address the first part of your question : Removing items earlier that a given date.



Kiss is your best friend. either you reasign the list after a filtering or you remove all the item you don't want based on a predicate.



var inputs = new List<CostCenter> {
new CostCenter("a", "70", "2019/11/10"),
new CostCenter("b", "30", "2019/11/10"),
new CostCenter("A", "40", "2018/10/05"),
new CostCenter("B", "60", "2018/10/05"),
new CostCenter("xx","10", "2010/01/01"),
new CostCenter("yy", "90", "2010/01/01"),
new CostCenter("100", "50", "2009/07/03"),
new CostCenter("101", "50", "2009/07/03"),
};

var result1 = inputs.Where(x => x.start > DateTime.Parse("2010/01/01")).ToList();
var result2 = inputs.RemoveAll(x=> x.start <= DateTime.Parse("2010/01/01"));





share|improve this answer


























  • I may be wrong, but this solution seems to be missing "also this fixed data will replace the earliest match" part.

    – Yeldar Kurmangaliyev
    Nov 26 '18 at 14:00











  • @YeldarKurmangaliyev, I din't get this part, if row 100 and 101 disapears without fixing the date. Why are the date of xx and yy changed.

    – xdtTransform
    Nov 26 '18 at 14:02











  • @xdtTransform your solution doesn't replace "xx" and "yy" with the start date to "2010/11/01"

    – DanielV
    Nov 26 '18 at 14:26











  • Not sure what you mean, sorry

    – DanielV
    Nov 27 '18 at 8:44











  • @DanielV, My bad I edited a new answer into this post then edited it out and post it as an other answer but system blocked my new answer. or ajax error .. I don't know but the new code was lost in the process. going thought edit history I got it back and push it as a new answer again .

    – xdtTransform
    Nov 27 '18 at 9:39





















2














First, you need to filter out all outdated items. Then, you can just take the first start, which is the earliest one, and then replace all with _earliestDate.



if (list == null)
throw new ArgumentNullException(...);

// Get rid of unused items and sort:
var actual = list
.Where(item => item.start >= _earliestDate)
.OrderByDescending(item => item.start)
.ToArray();

// If there are no matching items, then return empty array or throw exception
// It depends on your requirements
if (actual.Length == 0)
return actual;

// Take the least date in resulted array...
var earliestInActual = actual[actual.Length - 1];

// ...and replace it with _earliestDate
for (int i = actual.Length - 1; i >= 0; i--)
{
if (actual[i].start != earliestInActual)
break;

item.start = _earliestDate;
}

return actual;


Please, keep in mind that it will change original objects, therefore start dates will e updated in the original list as well.






share|improve this answer


























  • I think this is the closest to an answer out of all the ones posted, item.start > _earliestDate I think will remove too many results op wants to keep {"yy", 90, "2010/01/01"}

    – Matt
    Nov 26 '18 at 14:27











  • @Matt I have updated the answer with >=, thanks :)

    – Yeldar Kurmangaliyev
    Nov 26 '18 at 15:03



















1














Removing items from a list while using a foreach loop will cause it to lose it's position, you can however use a for loop or just do another loop removing all the flagged ones.



DateTime cutOffDate = DateTime.Parse("2010/11/01");

List<CostCenter> removeList = new List<CostCenter>();

foreach (var item in list.OrderByDescending(x => x.start).ToList())
{
if (item.start <= cutOffDate) {
removeList.Add(item);
}
}

foreach(var remove in removeList)
{
if (list.Contains(remove)) {
list.Remove(remove);
}
}





share|improve this answer
























  • Not sure I'm following, how will you lose data?

    – Matt
    Nov 26 '18 at 14:00











  • Your solution is not replacing the earliest match with the cutOffDate, please take a look at the requirement, I have updated the description to make it more clear.

    – DanielV
    Nov 26 '18 at 14:46



















1














We can create new filtered list with given criteria



        DateTime threshold = new DateTime(2010, 11, 01);
List<CostCenter> result = cc.Where(x => x.start.Date > threshold.Date).ToList();


POC : .netFiddle






share|improve this answer
























  • Same, this solution seems to be missing "also this fixed data will replace the earliest match" part.

    – Yeldar Kurmangaliyev
    Nov 26 '18 at 14:00











  • @YeldarKurmangaliyev, can you please elaborate on this

    – Prasad Telkikar
    Nov 26 '18 at 14:05











  • @PrasadTelkikar your answer is not addressing the requirement as Yeldar is commenting

    – DanielV
    Nov 26 '18 at 14:40



















1














For a List where 99% of the elements has to be removed, you will currently iterate throught the whole list to find all those elments and removing them.

Instead of clearing the List select only the part you wan't and stop as soon as you have Date inferior to earliestDate.
With a "TakeWhile" approach just add a flag to know when to edit the element to fix the date.



public static IEnumerable<CostCenter> TakeWhileAndOneAfter
(IEnumerable<CostCenter> source, DateTime splitDate )
{
DateTime? earliestDate = null;
bool earliestFound = false;

foreach (CostCenter element in source)
{
if (!earliestFound && !(element.start > splitDate))
{
earliestFound = true;
earliestDate = element.start;
}

if (earliestFound)
{
if (element.start < earliestDate)
{
break;
}
else
{
element.start = splitDate;
}
}
yield return element;
}
}





share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53482336%2fremove-items-earlier-than-a-fix-date-and-replace-the-first-occurrence%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    5 Answers
    5






    active

    oldest

    votes








    5 Answers
    5






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    4














    To address the first part of your question : Removing items earlier that a given date.



    Kiss is your best friend. either you reasign the list after a filtering or you remove all the item you don't want based on a predicate.



    var inputs = new List<CostCenter> {
    new CostCenter("a", "70", "2019/11/10"),
    new CostCenter("b", "30", "2019/11/10"),
    new CostCenter("A", "40", "2018/10/05"),
    new CostCenter("B", "60", "2018/10/05"),
    new CostCenter("xx","10", "2010/01/01"),
    new CostCenter("yy", "90", "2010/01/01"),
    new CostCenter("100", "50", "2009/07/03"),
    new CostCenter("101", "50", "2009/07/03"),
    };

    var result1 = inputs.Where(x => x.start > DateTime.Parse("2010/01/01")).ToList();
    var result2 = inputs.RemoveAll(x=> x.start <= DateTime.Parse("2010/01/01"));





    share|improve this answer


























    • I may be wrong, but this solution seems to be missing "also this fixed data will replace the earliest match" part.

      – Yeldar Kurmangaliyev
      Nov 26 '18 at 14:00











    • @YeldarKurmangaliyev, I din't get this part, if row 100 and 101 disapears without fixing the date. Why are the date of xx and yy changed.

      – xdtTransform
      Nov 26 '18 at 14:02











    • @xdtTransform your solution doesn't replace "xx" and "yy" with the start date to "2010/11/01"

      – DanielV
      Nov 26 '18 at 14:26











    • Not sure what you mean, sorry

      – DanielV
      Nov 27 '18 at 8:44











    • @DanielV, My bad I edited a new answer into this post then edited it out and post it as an other answer but system blocked my new answer. or ajax error .. I don't know but the new code was lost in the process. going thought edit history I got it back and push it as a new answer again .

      – xdtTransform
      Nov 27 '18 at 9:39


















    4














    To address the first part of your question : Removing items earlier that a given date.



    Kiss is your best friend. either you reasign the list after a filtering or you remove all the item you don't want based on a predicate.



    var inputs = new List<CostCenter> {
    new CostCenter("a", "70", "2019/11/10"),
    new CostCenter("b", "30", "2019/11/10"),
    new CostCenter("A", "40", "2018/10/05"),
    new CostCenter("B", "60", "2018/10/05"),
    new CostCenter("xx","10", "2010/01/01"),
    new CostCenter("yy", "90", "2010/01/01"),
    new CostCenter("100", "50", "2009/07/03"),
    new CostCenter("101", "50", "2009/07/03"),
    };

    var result1 = inputs.Where(x => x.start > DateTime.Parse("2010/01/01")).ToList();
    var result2 = inputs.RemoveAll(x=> x.start <= DateTime.Parse("2010/01/01"));





    share|improve this answer


























    • I may be wrong, but this solution seems to be missing "also this fixed data will replace the earliest match" part.

      – Yeldar Kurmangaliyev
      Nov 26 '18 at 14:00











    • @YeldarKurmangaliyev, I din't get this part, if row 100 and 101 disapears without fixing the date. Why are the date of xx and yy changed.

      – xdtTransform
      Nov 26 '18 at 14:02











    • @xdtTransform your solution doesn't replace "xx" and "yy" with the start date to "2010/11/01"

      – DanielV
      Nov 26 '18 at 14:26











    • Not sure what you mean, sorry

      – DanielV
      Nov 27 '18 at 8:44











    • @DanielV, My bad I edited a new answer into this post then edited it out and post it as an other answer but system blocked my new answer. or ajax error .. I don't know but the new code was lost in the process. going thought edit history I got it back and push it as a new answer again .

      – xdtTransform
      Nov 27 '18 at 9:39
















    4












    4








    4







    To address the first part of your question : Removing items earlier that a given date.



    Kiss is your best friend. either you reasign the list after a filtering or you remove all the item you don't want based on a predicate.



    var inputs = new List<CostCenter> {
    new CostCenter("a", "70", "2019/11/10"),
    new CostCenter("b", "30", "2019/11/10"),
    new CostCenter("A", "40", "2018/10/05"),
    new CostCenter("B", "60", "2018/10/05"),
    new CostCenter("xx","10", "2010/01/01"),
    new CostCenter("yy", "90", "2010/01/01"),
    new CostCenter("100", "50", "2009/07/03"),
    new CostCenter("101", "50", "2009/07/03"),
    };

    var result1 = inputs.Where(x => x.start > DateTime.Parse("2010/01/01")).ToList();
    var result2 = inputs.RemoveAll(x=> x.start <= DateTime.Parse("2010/01/01"));





    share|improve this answer















    To address the first part of your question : Removing items earlier that a given date.



    Kiss is your best friend. either you reasign the list after a filtering or you remove all the item you don't want based on a predicate.



    var inputs = new List<CostCenter> {
    new CostCenter("a", "70", "2019/11/10"),
    new CostCenter("b", "30", "2019/11/10"),
    new CostCenter("A", "40", "2018/10/05"),
    new CostCenter("B", "60", "2018/10/05"),
    new CostCenter("xx","10", "2010/01/01"),
    new CostCenter("yy", "90", "2010/01/01"),
    new CostCenter("100", "50", "2009/07/03"),
    new CostCenter("101", "50", "2009/07/03"),
    };

    var result1 = inputs.Where(x => x.start > DateTime.Parse("2010/01/01")).ToList();
    var result2 = inputs.RemoveAll(x=> x.start <= DateTime.Parse("2010/01/01"));






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 27 '18 at 7:09

























    answered Nov 26 '18 at 13:54









    xdtTransformxdtTransform

    433116




    433116













    • I may be wrong, but this solution seems to be missing "also this fixed data will replace the earliest match" part.

      – Yeldar Kurmangaliyev
      Nov 26 '18 at 14:00











    • @YeldarKurmangaliyev, I din't get this part, if row 100 and 101 disapears without fixing the date. Why are the date of xx and yy changed.

      – xdtTransform
      Nov 26 '18 at 14:02











    • @xdtTransform your solution doesn't replace "xx" and "yy" with the start date to "2010/11/01"

      – DanielV
      Nov 26 '18 at 14:26











    • Not sure what you mean, sorry

      – DanielV
      Nov 27 '18 at 8:44











    • @DanielV, My bad I edited a new answer into this post then edited it out and post it as an other answer but system blocked my new answer. or ajax error .. I don't know but the new code was lost in the process. going thought edit history I got it back and push it as a new answer again .

      – xdtTransform
      Nov 27 '18 at 9:39





















    • I may be wrong, but this solution seems to be missing "also this fixed data will replace the earliest match" part.

      – Yeldar Kurmangaliyev
      Nov 26 '18 at 14:00











    • @YeldarKurmangaliyev, I din't get this part, if row 100 and 101 disapears without fixing the date. Why are the date of xx and yy changed.

      – xdtTransform
      Nov 26 '18 at 14:02











    • @xdtTransform your solution doesn't replace "xx" and "yy" with the start date to "2010/11/01"

      – DanielV
      Nov 26 '18 at 14:26











    • Not sure what you mean, sorry

      – DanielV
      Nov 27 '18 at 8:44











    • @DanielV, My bad I edited a new answer into this post then edited it out and post it as an other answer but system blocked my new answer. or ajax error .. I don't know but the new code was lost in the process. going thought edit history I got it back and push it as a new answer again .

      – xdtTransform
      Nov 27 '18 at 9:39



















    I may be wrong, but this solution seems to be missing "also this fixed data will replace the earliest match" part.

    – Yeldar Kurmangaliyev
    Nov 26 '18 at 14:00





    I may be wrong, but this solution seems to be missing "also this fixed data will replace the earliest match" part.

    – Yeldar Kurmangaliyev
    Nov 26 '18 at 14:00













    @YeldarKurmangaliyev, I din't get this part, if row 100 and 101 disapears without fixing the date. Why are the date of xx and yy changed.

    – xdtTransform
    Nov 26 '18 at 14:02





    @YeldarKurmangaliyev, I din't get this part, if row 100 and 101 disapears without fixing the date. Why are the date of xx and yy changed.

    – xdtTransform
    Nov 26 '18 at 14:02













    @xdtTransform your solution doesn't replace "xx" and "yy" with the start date to "2010/11/01"

    – DanielV
    Nov 26 '18 at 14:26





    @xdtTransform your solution doesn't replace "xx" and "yy" with the start date to "2010/11/01"

    – DanielV
    Nov 26 '18 at 14:26













    Not sure what you mean, sorry

    – DanielV
    Nov 27 '18 at 8:44





    Not sure what you mean, sorry

    – DanielV
    Nov 27 '18 at 8:44













    @DanielV, My bad I edited a new answer into this post then edited it out and post it as an other answer but system blocked my new answer. or ajax error .. I don't know but the new code was lost in the process. going thought edit history I got it back and push it as a new answer again .

    – xdtTransform
    Nov 27 '18 at 9:39







    @DanielV, My bad I edited a new answer into this post then edited it out and post it as an other answer but system blocked my new answer. or ajax error .. I don't know but the new code was lost in the process. going thought edit history I got it back and push it as a new answer again .

    – xdtTransform
    Nov 27 '18 at 9:39















    2














    First, you need to filter out all outdated items. Then, you can just take the first start, which is the earliest one, and then replace all with _earliestDate.



    if (list == null)
    throw new ArgumentNullException(...);

    // Get rid of unused items and sort:
    var actual = list
    .Where(item => item.start >= _earliestDate)
    .OrderByDescending(item => item.start)
    .ToArray();

    // If there are no matching items, then return empty array or throw exception
    // It depends on your requirements
    if (actual.Length == 0)
    return actual;

    // Take the least date in resulted array...
    var earliestInActual = actual[actual.Length - 1];

    // ...and replace it with _earliestDate
    for (int i = actual.Length - 1; i >= 0; i--)
    {
    if (actual[i].start != earliestInActual)
    break;

    item.start = _earliestDate;
    }

    return actual;


    Please, keep in mind that it will change original objects, therefore start dates will e updated in the original list as well.






    share|improve this answer


























    • I think this is the closest to an answer out of all the ones posted, item.start > _earliestDate I think will remove too many results op wants to keep {"yy", 90, "2010/01/01"}

      – Matt
      Nov 26 '18 at 14:27











    • @Matt I have updated the answer with >=, thanks :)

      – Yeldar Kurmangaliyev
      Nov 26 '18 at 15:03
















    2














    First, you need to filter out all outdated items. Then, you can just take the first start, which is the earliest one, and then replace all with _earliestDate.



    if (list == null)
    throw new ArgumentNullException(...);

    // Get rid of unused items and sort:
    var actual = list
    .Where(item => item.start >= _earliestDate)
    .OrderByDescending(item => item.start)
    .ToArray();

    // If there are no matching items, then return empty array or throw exception
    // It depends on your requirements
    if (actual.Length == 0)
    return actual;

    // Take the least date in resulted array...
    var earliestInActual = actual[actual.Length - 1];

    // ...and replace it with _earliestDate
    for (int i = actual.Length - 1; i >= 0; i--)
    {
    if (actual[i].start != earliestInActual)
    break;

    item.start = _earliestDate;
    }

    return actual;


    Please, keep in mind that it will change original objects, therefore start dates will e updated in the original list as well.






    share|improve this answer


























    • I think this is the closest to an answer out of all the ones posted, item.start > _earliestDate I think will remove too many results op wants to keep {"yy", 90, "2010/01/01"}

      – Matt
      Nov 26 '18 at 14:27











    • @Matt I have updated the answer with >=, thanks :)

      – Yeldar Kurmangaliyev
      Nov 26 '18 at 15:03














    2












    2








    2







    First, you need to filter out all outdated items. Then, you can just take the first start, which is the earliest one, and then replace all with _earliestDate.



    if (list == null)
    throw new ArgumentNullException(...);

    // Get rid of unused items and sort:
    var actual = list
    .Where(item => item.start >= _earliestDate)
    .OrderByDescending(item => item.start)
    .ToArray();

    // If there are no matching items, then return empty array or throw exception
    // It depends on your requirements
    if (actual.Length == 0)
    return actual;

    // Take the least date in resulted array...
    var earliestInActual = actual[actual.Length - 1];

    // ...and replace it with _earliestDate
    for (int i = actual.Length - 1; i >= 0; i--)
    {
    if (actual[i].start != earliestInActual)
    break;

    item.start = _earliestDate;
    }

    return actual;


    Please, keep in mind that it will change original objects, therefore start dates will e updated in the original list as well.






    share|improve this answer















    First, you need to filter out all outdated items. Then, you can just take the first start, which is the earliest one, and then replace all with _earliestDate.



    if (list == null)
    throw new ArgumentNullException(...);

    // Get rid of unused items and sort:
    var actual = list
    .Where(item => item.start >= _earliestDate)
    .OrderByDescending(item => item.start)
    .ToArray();

    // If there are no matching items, then return empty array or throw exception
    // It depends on your requirements
    if (actual.Length == 0)
    return actual;

    // Take the least date in resulted array...
    var earliestInActual = actual[actual.Length - 1];

    // ...and replace it with _earliestDate
    for (int i = actual.Length - 1; i >= 0; i--)
    {
    if (actual[i].start != earliestInActual)
    break;

    item.start = _earliestDate;
    }

    return actual;


    Please, keep in mind that it will change original objects, therefore start dates will e updated in the original list as well.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 26 '18 at 15:03

























    answered Nov 26 '18 at 13:53









    Yeldar KurmangaliyevYeldar Kurmangaliyev

    24.9k93966




    24.9k93966













    • I think this is the closest to an answer out of all the ones posted, item.start > _earliestDate I think will remove too many results op wants to keep {"yy", 90, "2010/01/01"}

      – Matt
      Nov 26 '18 at 14:27











    • @Matt I have updated the answer with >=, thanks :)

      – Yeldar Kurmangaliyev
      Nov 26 '18 at 15:03



















    • I think this is the closest to an answer out of all the ones posted, item.start > _earliestDate I think will remove too many results op wants to keep {"yy", 90, "2010/01/01"}

      – Matt
      Nov 26 '18 at 14:27











    • @Matt I have updated the answer with >=, thanks :)

      – Yeldar Kurmangaliyev
      Nov 26 '18 at 15:03

















    I think this is the closest to an answer out of all the ones posted, item.start > _earliestDate I think will remove too many results op wants to keep {"yy", 90, "2010/01/01"}

    – Matt
    Nov 26 '18 at 14:27





    I think this is the closest to an answer out of all the ones posted, item.start > _earliestDate I think will remove too many results op wants to keep {"yy", 90, "2010/01/01"}

    – Matt
    Nov 26 '18 at 14:27













    @Matt I have updated the answer with >=, thanks :)

    – Yeldar Kurmangaliyev
    Nov 26 '18 at 15:03





    @Matt I have updated the answer with >=, thanks :)

    – Yeldar Kurmangaliyev
    Nov 26 '18 at 15:03











    1














    Removing items from a list while using a foreach loop will cause it to lose it's position, you can however use a for loop or just do another loop removing all the flagged ones.



    DateTime cutOffDate = DateTime.Parse("2010/11/01");

    List<CostCenter> removeList = new List<CostCenter>();

    foreach (var item in list.OrderByDescending(x => x.start).ToList())
    {
    if (item.start <= cutOffDate) {
    removeList.Add(item);
    }
    }

    foreach(var remove in removeList)
    {
    if (list.Contains(remove)) {
    list.Remove(remove);
    }
    }





    share|improve this answer
























    • Not sure I'm following, how will you lose data?

      – Matt
      Nov 26 '18 at 14:00











    • Your solution is not replacing the earliest match with the cutOffDate, please take a look at the requirement, I have updated the description to make it more clear.

      – DanielV
      Nov 26 '18 at 14:46
















    1














    Removing items from a list while using a foreach loop will cause it to lose it's position, you can however use a for loop or just do another loop removing all the flagged ones.



    DateTime cutOffDate = DateTime.Parse("2010/11/01");

    List<CostCenter> removeList = new List<CostCenter>();

    foreach (var item in list.OrderByDescending(x => x.start).ToList())
    {
    if (item.start <= cutOffDate) {
    removeList.Add(item);
    }
    }

    foreach(var remove in removeList)
    {
    if (list.Contains(remove)) {
    list.Remove(remove);
    }
    }





    share|improve this answer
























    • Not sure I'm following, how will you lose data?

      – Matt
      Nov 26 '18 at 14:00











    • Your solution is not replacing the earliest match with the cutOffDate, please take a look at the requirement, I have updated the description to make it more clear.

      – DanielV
      Nov 26 '18 at 14:46














    1












    1








    1







    Removing items from a list while using a foreach loop will cause it to lose it's position, you can however use a for loop or just do another loop removing all the flagged ones.



    DateTime cutOffDate = DateTime.Parse("2010/11/01");

    List<CostCenter> removeList = new List<CostCenter>();

    foreach (var item in list.OrderByDescending(x => x.start).ToList())
    {
    if (item.start <= cutOffDate) {
    removeList.Add(item);
    }
    }

    foreach(var remove in removeList)
    {
    if (list.Contains(remove)) {
    list.Remove(remove);
    }
    }





    share|improve this answer













    Removing items from a list while using a foreach loop will cause it to lose it's position, you can however use a for loop or just do another loop removing all the flagged ones.



    DateTime cutOffDate = DateTime.Parse("2010/11/01");

    List<CostCenter> removeList = new List<CostCenter>();

    foreach (var item in list.OrderByDescending(x => x.start).ToList())
    {
    if (item.start <= cutOffDate) {
    removeList.Add(item);
    }
    }

    foreach(var remove in removeList)
    {
    if (list.Contains(remove)) {
    list.Remove(remove);
    }
    }






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 26 '18 at 13:54









    MattMatt

    476210




    476210













    • Not sure I'm following, how will you lose data?

      – Matt
      Nov 26 '18 at 14:00











    • Your solution is not replacing the earliest match with the cutOffDate, please take a look at the requirement, I have updated the description to make it more clear.

      – DanielV
      Nov 26 '18 at 14:46



















    • Not sure I'm following, how will you lose data?

      – Matt
      Nov 26 '18 at 14:00











    • Your solution is not replacing the earliest match with the cutOffDate, please take a look at the requirement, I have updated the description to make it more clear.

      – DanielV
      Nov 26 '18 at 14:46

















    Not sure I'm following, how will you lose data?

    – Matt
    Nov 26 '18 at 14:00





    Not sure I'm following, how will you lose data?

    – Matt
    Nov 26 '18 at 14:00













    Your solution is not replacing the earliest match with the cutOffDate, please take a look at the requirement, I have updated the description to make it more clear.

    – DanielV
    Nov 26 '18 at 14:46





    Your solution is not replacing the earliest match with the cutOffDate, please take a look at the requirement, I have updated the description to make it more clear.

    – DanielV
    Nov 26 '18 at 14:46











    1














    We can create new filtered list with given criteria



            DateTime threshold = new DateTime(2010, 11, 01);
    List<CostCenter> result = cc.Where(x => x.start.Date > threshold.Date).ToList();


    POC : .netFiddle






    share|improve this answer
























    • Same, this solution seems to be missing "also this fixed data will replace the earliest match" part.

      – Yeldar Kurmangaliyev
      Nov 26 '18 at 14:00











    • @YeldarKurmangaliyev, can you please elaborate on this

      – Prasad Telkikar
      Nov 26 '18 at 14:05











    • @PrasadTelkikar your answer is not addressing the requirement as Yeldar is commenting

      – DanielV
      Nov 26 '18 at 14:40
















    1














    We can create new filtered list with given criteria



            DateTime threshold = new DateTime(2010, 11, 01);
    List<CostCenter> result = cc.Where(x => x.start.Date > threshold.Date).ToList();


    POC : .netFiddle






    share|improve this answer
























    • Same, this solution seems to be missing "also this fixed data will replace the earliest match" part.

      – Yeldar Kurmangaliyev
      Nov 26 '18 at 14:00











    • @YeldarKurmangaliyev, can you please elaborate on this

      – Prasad Telkikar
      Nov 26 '18 at 14:05











    • @PrasadTelkikar your answer is not addressing the requirement as Yeldar is commenting

      – DanielV
      Nov 26 '18 at 14:40














    1












    1








    1







    We can create new filtered list with given criteria



            DateTime threshold = new DateTime(2010, 11, 01);
    List<CostCenter> result = cc.Where(x => x.start.Date > threshold.Date).ToList();


    POC : .netFiddle






    share|improve this answer













    We can create new filtered list with given criteria



            DateTime threshold = new DateTime(2010, 11, 01);
    List<CostCenter> result = cc.Where(x => x.start.Date > threshold.Date).ToList();


    POC : .netFiddle







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 26 '18 at 13:56









    Prasad TelkikarPrasad Telkikar

    1,953419




    1,953419













    • Same, this solution seems to be missing "also this fixed data will replace the earliest match" part.

      – Yeldar Kurmangaliyev
      Nov 26 '18 at 14:00











    • @YeldarKurmangaliyev, can you please elaborate on this

      – Prasad Telkikar
      Nov 26 '18 at 14:05











    • @PrasadTelkikar your answer is not addressing the requirement as Yeldar is commenting

      – DanielV
      Nov 26 '18 at 14:40



















    • Same, this solution seems to be missing "also this fixed data will replace the earliest match" part.

      – Yeldar Kurmangaliyev
      Nov 26 '18 at 14:00











    • @YeldarKurmangaliyev, can you please elaborate on this

      – Prasad Telkikar
      Nov 26 '18 at 14:05











    • @PrasadTelkikar your answer is not addressing the requirement as Yeldar is commenting

      – DanielV
      Nov 26 '18 at 14:40

















    Same, this solution seems to be missing "also this fixed data will replace the earliest match" part.

    – Yeldar Kurmangaliyev
    Nov 26 '18 at 14:00





    Same, this solution seems to be missing "also this fixed data will replace the earliest match" part.

    – Yeldar Kurmangaliyev
    Nov 26 '18 at 14:00













    @YeldarKurmangaliyev, can you please elaborate on this

    – Prasad Telkikar
    Nov 26 '18 at 14:05





    @YeldarKurmangaliyev, can you please elaborate on this

    – Prasad Telkikar
    Nov 26 '18 at 14:05













    @PrasadTelkikar your answer is not addressing the requirement as Yeldar is commenting

    – DanielV
    Nov 26 '18 at 14:40





    @PrasadTelkikar your answer is not addressing the requirement as Yeldar is commenting

    – DanielV
    Nov 26 '18 at 14:40











    1














    For a List where 99% of the elements has to be removed, you will currently iterate throught the whole list to find all those elments and removing them.

    Instead of clearing the List select only the part you wan't and stop as soon as you have Date inferior to earliestDate.
    With a "TakeWhile" approach just add a flag to know when to edit the element to fix the date.



    public static IEnumerable<CostCenter> TakeWhileAndOneAfter
    (IEnumerable<CostCenter> source, DateTime splitDate )
    {
    DateTime? earliestDate = null;
    bool earliestFound = false;

    foreach (CostCenter element in source)
    {
    if (!earliestFound && !(element.start > splitDate))
    {
    earliestFound = true;
    earliestDate = element.start;
    }

    if (earliestFound)
    {
    if (element.start < earliestDate)
    {
    break;
    }
    else
    {
    element.start = splitDate;
    }
    }
    yield return element;
    }
    }





    share|improve this answer






























      1














      For a List where 99% of the elements has to be removed, you will currently iterate throught the whole list to find all those elments and removing them.

      Instead of clearing the List select only the part you wan't and stop as soon as you have Date inferior to earliestDate.
      With a "TakeWhile" approach just add a flag to know when to edit the element to fix the date.



      public static IEnumerable<CostCenter> TakeWhileAndOneAfter
      (IEnumerable<CostCenter> source, DateTime splitDate )
      {
      DateTime? earliestDate = null;
      bool earliestFound = false;

      foreach (CostCenter element in source)
      {
      if (!earliestFound && !(element.start > splitDate))
      {
      earliestFound = true;
      earliestDate = element.start;
      }

      if (earliestFound)
      {
      if (element.start < earliestDate)
      {
      break;
      }
      else
      {
      element.start = splitDate;
      }
      }
      yield return element;
      }
      }





      share|improve this answer




























        1












        1








        1







        For a List where 99% of the elements has to be removed, you will currently iterate throught the whole list to find all those elments and removing them.

        Instead of clearing the List select only the part you wan't and stop as soon as you have Date inferior to earliestDate.
        With a "TakeWhile" approach just add a flag to know when to edit the element to fix the date.



        public static IEnumerable<CostCenter> TakeWhileAndOneAfter
        (IEnumerable<CostCenter> source, DateTime splitDate )
        {
        DateTime? earliestDate = null;
        bool earliestFound = false;

        foreach (CostCenter element in source)
        {
        if (!earliestFound && !(element.start > splitDate))
        {
        earliestFound = true;
        earliestDate = element.start;
        }

        if (earliestFound)
        {
        if (element.start < earliestDate)
        {
        break;
        }
        else
        {
        element.start = splitDate;
        }
        }
        yield return element;
        }
        }





        share|improve this answer















        For a List where 99% of the elements has to be removed, you will currently iterate throught the whole list to find all those elments and removing them.

        Instead of clearing the List select only the part you wan't and stop as soon as you have Date inferior to earliestDate.
        With a "TakeWhile" approach just add a flag to know when to edit the element to fix the date.



        public static IEnumerable<CostCenter> TakeWhileAndOneAfter
        (IEnumerable<CostCenter> source, DateTime splitDate )
        {
        DateTime? earliestDate = null;
        bool earliestFound = false;

        foreach (CostCenter element in source)
        {
        if (!earliestFound && !(element.start > splitDate))
        {
        earliestFound = true;
        earliestDate = element.start;
        }

        if (earliestFound)
        {
        if (element.start < earliestDate)
        {
        break;
        }
        else
        {
        element.start = splitDate;
        }
        }
        yield return element;
        }
        }






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 27 '18 at 9:58

























        answered Nov 27 '18 at 9:35









        xdtTransformxdtTransform

        433116




        433116






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53482336%2fremove-items-earlier-than-a-fix-date-and-replace-the-first-occurrence%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Lallio

            Unable to find Lightning Node

            Futebolista