0

I am trying to find a way to detect if there is/are the same text in array input, all five of the Name input must be different, and if there is any similarity, it will automatically request input again.

Example:

Name 1: Max
Address 1: address a

Name 2: Max
Address 2: address b

You can see that both of the name input is similar, i want it to Console.WriteLine("The name is already added, please add a different name); and request input for Name 2 again.

Just like this:

Name 1: Max
Address 1: address a

Name 2: Max
Address 2: address b

Name is already added, Please input a different name!`
Name 2: Minimum

Here is my code so far:

    var a = 5;
    string[,] input = new string[a, 2];

    for (a = 0; a < 5; a++)
    {
        Console.Write($"Name {a + 1} : ");
        input[a, 0] = Console.ReadLine();
        input[a, 0] = input[a, 0].ToLower();
        Console.Write($"Address {a + 1} : ");
        input[a, 1] = Console.ReadLine();
        
    }

NOTE: This is between five inputs

Dai
  • 141,631
  • 28
  • 261
  • 374
Cologne
  • 5
  • 1
  • Check those : 1- https://stackoverflow.com/questions/7867377/checking-if-a-string-array-contains-a-value-and-if-so-getting-its-position/7867403 2- https://stackoverflow.com/questions/10709821/find-text-in-string-with-c-sharp – Buğra Demirtaş Nov 25 '21 at 18:13
  • You don't need an array, you should use a `HashSet` or some kind of Dictionary instead. – Dai Nov 25 '21 at 18:14

2 Answers2

1

You can use HashSet<string> to store unique strings (names):

  //DONE: it's unclear what "a" name means, let it be "count"
  var count = 5;
  //TODO: I've kept 2d array from the question, 
  // a class (tuple) will be better here 
  string[,] input = new string[count, 2];
  
  var takenNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

  //DONE: don't use magic constants - 5
  for (int i = 0; i < input.GetLength(0); ++i) {
    // Keep asking user until unique name is provided:
    while (true) {
      Console.Write($"Name {i + 1} : ");
      input[i, 0] = Console.ReadLine();

      // stop asking if and only if the name is unique  
      if (takenNames.Add(input[i, 0]))
        break;

      Console.WriteLine("Name is already added, Please input a different name!");
    }   

    Console.Write($"Address {i + 1} : ");
    input[i, 1] = Console.ReadLine();       
  }

Edit: As Dai mentioned in the comments, an array of custom classes, named tuples, records etc. is better design then 2d array of strings, e.g.

  var count = 5;
  // let it be readable: named tuple with name and address properties  
  var input = new (string name, string address)[count];

  var takenNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

  for (int i = 0; i < input.GetLength(0); ++i) {
    // Keep asking user until unique name is provided:
    while (true) {
      Console.Write($"Name {i + 1} : ");
      input[i].name = Console.ReadLine();

      // stop asking if and only if the name is unique  
      if (takenNames.Add(input[i].name))
        break;

      Console.WriteLine("Name is already added, Please input a different name!");
    }

    Console.Write($"Address {i + 1} : ");
    input[i].address = Console.ReadLine();
  }
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • Good stuff - though that `string[,]` (from the OP's code, I know) with const/literal indexes makes me wince - can you change it to use a ValueTuple with named members instead? – Dai Nov 25 '21 at 18:29
  • @Dai: I vote for a *custom class* and, probably, with overriden `Equals` and `GetHashCode` for easier duplicate check. I totally agree with you that `string[,]` is (very) bad design here, but changing to named tuples can well ruin business logic which manipulates with `string[,]`, that's why I stuck to `string[,]`. I've edited the answer and provide a version with named tuple. – Dmitry Bychenko Nov 25 '21 at 18:44
0

Here is a basic example. You can cut and paste into Linqpad to try it

EDIT Corrected to take into account @Dai comment about the Dictionary constructor overload that takes an IEqualityComparer instance as argument. See the doc about this constructor, and the doc about the StringComparer.

void Main()
{
    var personCount = 5;
    var persons = new Dictionary<string, Person>(StringComparer.OrdinalIgnoreCase);
    
    for (int i = 0; i < personCount; i++)
    {
        var newPerson = new Person();
        Console.WriteLine("Enter a name");
        var name = Console.ReadLine();
        while(persons.ContainsKey(name))
        {
            Console.WriteLine("This name already exists, please enter a new name");
            name = Console.ReadLine();
        }
        newPerson.Name = name;
        Console.WriteLine("Enter an address");
        newPerson.Address = Console.ReadLine();
        persons.Add(name, newPerson);
    }
}

// You can define other methods, fields, classes and namespaces here

public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }
}
Laurent Gabiot
  • 1,251
  • 9
  • 15
  • Please don't use `PascalCase` for locals. We aren't writing VB6 here. – Dai Nov 25 '21 at 18:26
  • `Persons.Add(Name.ToLower(), NewPerson);` <-- This is incorrect. Don't use `.ToLower()` for the sake of case-insensitive string keys in a dictionary. Instead pass `StringComparer.OrdinalIgnoreCase` into the `Dictionary` constructor. – Dai Nov 25 '21 at 18:28
  • Thanks! I should have looked in the Dictionary overloads. I'll remember this. I'll correct my post. – Laurent Gabiot Nov 25 '21 at 18:51