1

I am working to make a database from scratch. I have a jagged called data array, I try to clone(lns) it, the clone(lns) becomes lower case and so data becomes too. But I do not want that! How can I prevent this? ignorecase is true. If I set that to false, the problem no longer occurs.

You may do not believe it, at least I don't, so I uploaded a video.

    public string[][] getRows(string[][] data, int columnLength, int index = -1, string arg = "", bool ignoreCase = false, bool getContaining = false)
    {
        if (index >= columnLength) return null; // I love null!
        if (!getContaining && arg == "") return data;

        string[][] toReturn = new string[data.Length][];
        string[][] lns = data;
        int a = 0;

        if (ignoreCase)
        {
            arg = arg.ToLower();
            for (int i = 0; i < columnLength; i++)
                for (int j = 0; j < lns.Length; j++)
                    lns[j][i] = lns[j][i].ToLower();
        }



        if (index >= 0)
        {
            if (getContaining)
            {
                for (int i = 0; i < data.Length; i++)
                    if (lns[i][index].Contains(arg))
                    {
                        toReturn[a] = data[i];
// code continues...

EDIT: Okay, I do know now that lns = data doesn't make a clone, but just makes another variable. But how can I clone this so I can execute this code?

joppiesaus
  • 5,471
  • 3
  • 26
  • 36

2 Answers2

5

In string[][] lns = data;, no copy/clone/duplicate of the data array is being made during the assignment.

So lns[j][i] = lns[j][i].ToLower(); is equivalent to data[j][i] = data[j][i].ToLower(); which modifies the original data/array.

I would simply move the case-insensitive compare to the condition itself. Trivially, that might look like the following - remember to remove the original if (ignoreCase) {..} code.

// Move logic to condition (don't change any data)
  if (ignoreCase && lns[i][index].ToLower().Contains(arg.ToLower())
      || lns[i][index].Contains(arg)) {
    toReturn[a] = data[i];
    // ..

For neater case-insensitive alternatives, see Case insensitive 'Contains(string)' and/or consider using a predicate lambda/function.


Well, since I did mention "neater" ways above..

// Predicate methods (defined in class) 
bool ContainsSensitive (string a, string b) {
   return a.Contains(b);
}
bool ContainsInsensitive (string a, string b) {
   // From https://stackoverflow.com/a/444818/2864740
   return a.IndexOf(b, StringComparison.OrdinalIgnoreCase) >= 0;
}

// In function:
Func<string,string,bool> contains = ignoreCase
    ? ContainsInsensitive
    : ContainsSensitive;

// Move logic to condition, but use predicate function to move
// the actual logic elsewhere.
  if (contains(lns[i][index], arg)) {
    toReturn[a] = data[i];
    // ..

Just some wonderfulness of C# to look forward to .. I'd probably use LINQ/IEnumerable instead of arrays as well.

Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220
2

This line:

string[][] lns = data;

Does not "clone" the array (by which I assume you mean creating a duplicate array of the same size/shape with the same values in the corresponding slots). You have one array in memory stored in your data variable. This simply declares a new lns variable and points it to the same array. Any changes made through one variable will be the same if you access the other variable.

This is true for all reference types. For a more detailed explanation, see this article by Jon Skeet.

Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
  • How can I make a duplicate/copy of the string[][]? – joppiesaus Feb 28 '14 at 19:35
  • 2
    @joppiesaus: For a jagged array, you'll have to do it manually. There is no quick way to do it. That said, you should not use lowercase to perform case-insensitive string comparisons. Use `String.Compare` instead and indicate that the comparison should be case insensitive. – Adam Robinson Feb 28 '14 at 19:39