Click here to Skip to main content
15,891,529 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi guys,
i have a
C#
List<string>
that contains elements of type "S1-00-1001" "S1-00-1002" and so on up to "S1-00-1200" consecutive,
then other element "S1-00-1501" "S1-00-1502" and so on up to "S1-00-1600" consecutive and many other elements.

In general i want that my output would be like:

ticket from "S1-00-1001" to "S1-00-1200"
ticket from "S1-00-1501" to "S1-00-1600"
........
........

How I can calculate the set of the sequential string?
I hope that you understand my problem.
Many thanks for any response, sorry for my english.
Posted
Updated 10-May-14 11:42am
v2
Comments
BillWoodruff 10-May-14 19:21pm    
Is it always the case that each List item will be of the form two-characters - two characters - four characters ?

Does it matter if the groups are sorted ?

Supposing all strings are always equal in format (and using pseudo code):

declare a variable to save the last checked number

make a loop that go through the list
   get the current element
   extract the last block of numbers
   transform the last block of numbers into a number
   if it is the first iteration of the loop
      start a group and save the actual string in it
      save the converted number into the variable declared before
      go to next iteration

   if it is not the first iteration of the loop
      if there is no saved value in the variable
         start a group and save the actual string in it
         save the converted number into the variable declared before
         go to next iteration
      else
         compare the converted number with (last number saved + 1)
         // if consecutive can be both directions, then you have to compare it |saved - current| = 1

         if the comparison of consecutive is successful
            save the current string into the actual group
            save the current number into the variable to check the next one
            go to the next iteration
         else
            end your actual group
            start a new one and add the current string in it
            go to next iteration

   when iteration ended
      give the results you need
 
Share this answer
 
v5
Comments
BillWoodruff 10-May-14 21:54pm    
+5 very well thought-out strategy ! The hard-part is, of course, figuring out a way to use Linq's powerful tools to achieve it.
Nelek 11-May-14 12:10pm    
Thanks Bill
I'm sure it is not best way but it is working, maybe it gives you a hint to fix it or find your own method;

First, let's fill list with dummy values;

C#
List<string> list = new List<string>();

Enumerable.Range(0, 10).ToList().ForEach(p => list.Add("S1-00-" + (p + 220).ToString().PadLeft(4, '0')));
Enumerable.Range(0, 10).ToList().ForEach(p => list.Add("S1-00-" + p.ToString().PadLeft(4, '0')));
Enumerable.Range(0, 10).ToList().ForEach(p => list.Add("S1-00-" + (p+100).ToString().PadLeft(4, '0')));
Enumerable.Range(0, 10).ToList().ForEach(p => list.Add("S1-00-" + (p + 380).ToString().PadLeft(4, '0')));


Then we need to sort list with our method;

C#
list.Sort((a, b) => ExtractNumber(a).CompareTo(ExtractNumber(b)));

//Here's the result
var result = GetGroups(list).ToList();


Methods;

C#
private int ExtractNumber(string text)
{
    var asd = new string(text.Reverse().TakeWhile(char.IsDigit).Reverse().ToArray());
    int result = 0;
    int.TryParse(asd, out result);
    return result;
}

private IEnumerable<IEnumerable><string>> GetGroups(List<string> list)
{
    while (list.Any())
    {
        if (list.Count == 1)
        {
            var single = list;
            list = list.Except(single).ToList();
            yield return single;
        }
        else
        {
            var sequentialList = list.TakeWhile((a, b) => ExtractNumber(list[b + 1 >= list.Count ? b : b + 1]) - ExtractNumber(list[b]) == 1).ToList();
            list = list.Except(sequentialList).ToList();
            sequentialList = sequentialList.Concat(list.Take(1)).ToList();
            list.RemoveAt(0);

            yield return sequentialList;
        }
    }
}


If you notice any wrongs, please tell me.
 
Share this answer
 
v5
Comments
BillWoodruff 10-May-14 21:56pm    
+5 extremely creative use of Linq ! I suspect there is a simpler way to do it, however.
hi guys,
i think i've solved my problem this way:

C#
List<object> series = new List<object>();
series = FindSeries(consecutive);


consecutive is the list with items like the first example

with the method:

C#
public List<object> FindSeries(List<object> list)
        {
            List<object> series = new List<object>();
            //first
            series.Add(list[0]);

            for(int i = 1; i < list.Count; i++)
            {
                var checkNext = list[i].ToString().Split('-');
                var checkPrev = list[i - 1].ToString().Split('-');

                int valueOfNext = Convert.ToInt32(checkNext[2]);
                int valueOfPrev = Convert.ToInt32(checkPrev[2]);

                if(valueOfNext - 1 != valueOfPrev)
                {
                    series.Add(list[i - 1]);
                    series.Add(list[i]);
                }
            }

            //last
            series.Add(list[list.Count - 1]);

            return series;
        }


for now it works, I'll try to improve the solution
 
Share this answer
 
Comments
Nelek 13-May-14 5:03am    
Good job :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900