user6807975
user6807975

Reputation: 135

Get first occurence of a char from a string

First of all, I'd like to point out that the desired result is a char, not its position index (int).
I'm trying to give my users an option of choosing their desired date format and as such, I've created 2 comboBoxes: comboBox_DateFormatDivider where user chooses between dot, dash and a slash; and comboBox_DateFormat where user chooses date format. comboBox_DateFormat contains a List<string> as follows:

_dateFormatsList = new List<string>()
{
    "d-M-yy (" + DateTime.Now.ToString("d-M-yy") + ")",
    "dd-M-yy (" + DateTime.Now.ToString("dd-M-yy") + ")",
    "d-MM-yy (" + DateTime.Now.ToString("d-MM-yy") + ")",
    "dd-MM-yy (" + DateTime.Now.ToString("dd-MM-yy") + ")",
    "d-M-yyyy (" + DateTime.Now.ToString("d-M-yyyy") + ")",
    "dd-M-yyyy (" + DateTime.Now.ToString("dd-M-yyyy") + ")",
    "d-MM-yyyy (" + DateTime.Now.ToString("d-MM-yyyy") + ")",
    "dd-MM-yyyy (" + DateTime.Now.ToString("dd-MM-yyyy") + ")",
    "yy-M-d (" + DateTime.Now.ToString("yy-M-d") + ")",
    "yy-M-dd (" + DateTime.Now.ToString("yy-M-dd") + ")",
    "yy-MM-d (" + DateTime.Now.ToString("yy-MM-d") + ")",
    "yy-MM-dd (" + DateTime.Now.ToString("yy-MM-dd") + ")",
    "yyyy-M-d (" + DateTime.Now.ToString("yyyy-M-d") + ")",
    "yyyy-M-dd (" + DateTime.Now.ToString("yyyy-M-dd") + ")",
    "yyyy-MM-d (" + DateTime.Now.ToString("yyyy-MM-d") + ")",
    "yyyy-MM-dd (" + DateTime.Now.ToString("yyyy-MM-dd") + ")"
};
comboBox_DateFormat.DataSource = _dateFormatsList;

When user chooses different divider, it has to be reflected in the other comboBox, as such DateFormat is dependent on DateFormatDivider, so its contents have to be changed at runtime. And here's the code (and the question) for that:

private void comboBox_DateFormatDivider_SelectedIndexChanged(object sender, EventArgs e)
{
    for (int i = 0; i < _dateFormatsList.Count; i++)
    {
        _dateFormatsList[i] = _dateFormatsList[i].Replace(_dateFormatsList[i].???.ToString(), comboBox_DateFormatDivider.SelectedText);
    }
}

Chosen date format is later saved to database, so I guess I could also add another field where divider would be stored, but I'd prefer not to. As you can see, the code above contains ??? in it. So, the question is: how do I replace these question marks with code that will find me the divider it contains?

Upvotes: 0

Views: 111

Answers (3)

Mrinal Kamboj
Mrinal Kamboj

Reputation: 11478

Assuming that number of dividers in the Date format are finite, I will do the following:

List<string> dividers = new List<string>{".","/","-"}

private void comboBox_DateFormatDivider_SelectedIndexChanged(object sender, EventArgs e)
{
    string currentSeparator = string.Empty;

     foreach(var s in dividers)
     {
     string pattern = @".*(?:\" + s + ").*";

        if(Regex.IsMatch(_dateFormatsList[0],pattern))
        {
          currentSeparator = s;
          break;    
         }    
     }
    for (int i = 0; i < _dateFormatsList.Count; i++)
    {
        _dateFormatsList[i] = _dateFormatsList[i].Replace(currentSeparator, comboBox_DateFormatDivider.SelectedText);
    }
}

Edit 1:

Explanation about regular expression:

Following are details: ".*(?:\.).*", .* means anything which means 0 or more occurrence, of any character, ?: refers to pattern search matching starts and it expects the character being passed (here "."), (which is escaped, to avoid special treatment of special characters like ., *, ? etc) to be searched in all the data an it will return true on first occurrence or else false.

Edit 2:

To provide an example of the potential of Regular expressions, in the _dateFormatsList, you have multiple date formats, but all the solutions, just pick one value to figure out operator, what about the other values, what if there's data corruption and more than one separators exist, following code will take care of lot of such issues and can further be made strict by changing the pattern:

string pattern = @"^(?!\.\/)[\d]{1,4}[\-][\d]{1,2}[\-][\d]{1,4}$";

It represent all the date formats which contains separator - but not . or /, also there's a digit (\d) repetition, before a separator -, this pattern needs to be applied using Linq All operator as follows:

bool result = _dateFormatsList.All(data => Regex.IsMatch(data,pattern));

This is just to depict, the power of Regular expressions, which no other solution can help achieve, I think most people find Regex complex due to lack of understanding regarding pattern creation

Upvotes: 1

Abion47
Abion47

Reputation: 24671

During those rare cases where you absolutely must do string searching, you can just do the following:

string[] separators = new string[] { "-", ".", "/" };

void DetectCurrentSeparator(string dbDateFormat)
{
    for (int i = 0; i < separators.Length; i++)
    {
        if (dbDateFormat.IndexOf(separators[i]) >= 0)
        {
            // Assuming the above array corresponds with the order of the divider combobox
            combobox_DateFormatDivider.SelectedIndex = i;
            break;
        }
    }
}

Now this having been said, this method should only need to ever be used once during the life of your program - when the date format is first retrieved from the database. For the rest of the time, there is no reason to use any string searching at all for this. You already have the desired divider from your combo box, so instead of trying to figure out what the existing divider is, use a common temporary character and just replace that.

Initialize like so:

DateTime now = DateTime.Now;
_dateFormatsMasterList = new List<string>()
{
    "d@M@yy (" + now.ToString("d@M@yy") + ")",
    "dd@M@yy (" + now.ToString("dd@M@yy") + ")",
    "d@MM@yy (" + now.ToString("d@MM@yy") + ")",
    "dd@MM@yy (" + now.ToString("dd@MM@yy") + ")",
    "d@M@yyyy (" + now.ToString("d@M@yyyy") + ")",
    "dd@M@yyyy (" + now.ToString("dd@M@yyyy") + ")",
    "d@MM@yyyy (" + now.ToString("d@MM@yyyy") + ")",
    "dd@MM@yyyy (" + now.ToString("dd@MM@yyyy") + ")",
    "yy@M@d (" + now.ToString("yy@M@d") + ")",
    "yy@M@dd (" + now.ToString("yy@M@dd") + ")",
    "yy@MM@d (" + now.ToString("yy@MM@d") + ")",
    "yy@MM@dd (" + now.ToString("yy@MM@dd") + ")",
    "yyyy@M@d (" + now.ToString("yyyy@M@d") + ")",
    "yyyy@M@dd (" + now.ToString("yyyy@M@dd") + ")",
    "yyyy@MM@d (" + now.ToString("yyyy@MM@d") + ")",
    "yyyy@MM@dd (" + now.ToString("yyyy@MM@dd") + ")"
};

_dateFormatsList = new List<string>(_dateFormatsMasterList);
comboBox_DateFormat.DataSource = _dateFormatsList;

And your SelectionChanged event like so:

private void comboBox_DateFormatDivider_SelectedIndexChanged(object sender, EventArgs e)
{
    for (int i = 0; i < _dateFormatsList.Count; i++)
    {
        _dateFormatsList[i] = _dateFormatsMasterList[i].Replace("@", comboBox_DateFormatDivider.SelectedText);
    }
}

Upvotes: 2

hitesh sharma
hitesh sharma

Reputation: 69

first of all, i'd like to go with Abion47's advice to use a variable to store date and use it in the list.

and then you can do this

char x = _dateFormatsList[0][1];
        for (int i = 0; i < _dateFormatsList.Count; i++)
            {
                _dateFormatsList[i] = _dateFormatsList[i].Replace(x, comboBox_DateFormatDivider.SelectedItem.ToString()[0]);
            }

Upvotes: 0

Related Questions