сравнить массив строк, используя коллекцию - PullRequest
4 голосов
/ 10 марта 2010

У меня есть два массива String a, b.

String a [] = {"one","two","three"};
String b [] = {"one","Two","Three","four"};

Мне нужно проверить, одинаковы ли оба массива, с учетом регистра. Я знаю, следующий фрагмент кода идеально подходит для учета регистра.

List <String> l1 = Arrays.asList(a);
List <String> l2 = Arrays.asList(b);
System.out.println(l2.containsAll(l1));  

Есть ли другой способ сравнить массив из двух строк (без учета регистра), используя коллекцию?

Ответы [ 8 ]

4 голосов
/ 11 марта 2010

Наконец, я использовал TreeSet с нечувствительным к регистру компаратором.

Пример:

 String [] oldVal = {"one","two","three","Four"};
 String [] newVal = {"one","Two","Three","four"};

 Set <String> set1 = new TreeSet <String> (String.CASE_INSENSITIVE_ORDER);
 Set <String> set2 = new TreeSet <String> (String.CASE_INSENSITIVE_ORDER);

 set1.addAll(Arrays.asList(oldVal));
 set2.addAll(Arrays.asList(newVal));

 System.out.println("--Using Tree Set --- "+ set1.containsAll(set2));  // Return True

Спасибо, ребята ..

1 голос
/ 11 марта 2010

Вы можете использовать TreeMap с нечувствительным к регистру компаратором.

1 голос
/ 11 марта 2010

Если массивы не содержат дубликатов , один из способов сделать это в O(N) - использовать Set, представляющий каноническую форму строк в массиве. Как то так:

static Set<String> canonicalSet(String[] arr) {
    Set<String> upperSet = new HashSet<String>();
    for (String s : arr) {
        upperSet.add(s.toUpperCase());
    }
    return upperSet;
}
static boolean equalsCanonically(String[] arr1, String[] arr2) {
    return canonicalSet(arr1).equals(canonicalSet(arr2));
}

Это оптимальное время.

Вы также можете изменять эту технику, чтобы сэкономить больше места, например, вместо построения канонических наборов и их сравнения вы можете создать канонический набор для arr1, а затем удалить записи из этого набора в соответствии с элементами arr2. Если после этого набор пуст, и вы всегда можете найти то, что вам нужно удалить, эти два массива канонически равны.

static boolean equalsCanonically2(String[] arr1, String[] arr2) {
    Set<String> canon = canonicalSet(arr1);
    for (String s : arr2) {
        if (!canon.remove(s.toUpperCase())) return false;
    }
    return canon.isEmpty();
}

Вы также можете выполнить простую проверку сравнения размеров, если считаете, что оно того стоит (т. Е. Если часто два массива даже не имеют одинаковое количество элементов).

Если в массивах есть дубликаты, метод Set не будет работать как есть. Вам понадобится мультимножество, и вы можете либо реализовать свой собственный, либо использовать Google Collections '.


Есть также O(N log N) способы сделать это, включая сортировку строк. Вы можете отсортировать оба массива, а затем выполнить простую линейную проверку. Необходимо использовать регистр без учета регистра, и фактически он уже существует как String.CASE_INSENSITIVE_ORDER.

static boolean equalsCanonically3(String[] arr1, String[] arr2) {
    int N = arr1.length;
    if (arr2.length != N) return false;
    Arrays.sort(arr1, String.CASE_INSENSITIVE_ORDER);
    Arrays.sort(arr2, String.CASE_INSENSITIVE_ORDER);
    for (int i = 0; i < N; i++) {
        if (String.CASE_INSENSITIVE_ORDER.compare(arr1[i], arr2[i]) != 0) {
            return false;
        }
    }
    return true;
}

Эта последняя техника работает, даже если массивы содержат дубликаты. Это делает это O(N log N). Он сортирует массивы, переданные в качестве параметров, поэтому, если исходное состояние важно, вы должны передать вместо них clone().

1 голос
/ 10 марта 2010

Не могли бы вы просто зациклить его или использовать какой-нибудь linq (Извините, только что заметил, что это Java, вы не можете использовать linq ...?)

    List<string> matches = new List<string>();
    bool isSame=true;

    foreach(string s1 in l1)
     {
      foreach(string s2 in l2)
        {
         if(s1.ToLower() == s2.ToLower()) 
          matches.Add(s1);
         else
            {
             isSame=false;
             break;
            }
        }
       if (isSame) 
            continue;           
       else
            break;
     }

if (isSame)
    Console.Writeline("They are the same")
else
    Console.Writeline("Not the same");

Возможно, вы захотите проверить счетчик, поскольку я не добавил его в код, например, l1.count> l2.count (в этом случае вы знаете, одинаковы ли они по количеству элементов в списке ). Простой тест даже перед циклом:

if (l1.Count != l2.Count) {
 //don't even bother looping
 //display no matches
}
else {
 //place rest of code here since l1.count = l2.count
}
  • Крэп не понял, что это было для Java, хотя это было для C #. ПРИМЕНЯТЬ ЖЕ ЛОГИКА ЧЕРЕЗ JAVA ...
0 голосов
/ 11 марта 2010

Использование одного для цикла -

String [] oldVal = {"one","two","three","Four"};
String [] newVal = {"one","Two","Three","four"};


if(oldVal.length == newVal.length)
{
 //
 for(int y =0; y<oldVal.length; y++)
 {
  oldVal[y] = oldVal[y].toUpperCase();
  newVal[y] = newVal[y].toUpperCase();
 }

 return Arrays.asList(oldVal).containsAll(Arrays.asList(newVal));

}
 return false;  
0 голосов
/ 11 марта 2010

Вы могли бы сначала проверить, равны ли их длины. Затем вы можете положить элементы a в HashMap, перейти на b и проверить, есть ли эти элементы.

0 голосов
/ 10 марта 2010

Ваш пример данных отсортирован. Если это действительно так, то вам следует поступить так, как говорит Андрей, и использовать вложенные циклы на самих массивах, разрывая их, если / когда вы найдете неравную пару записей.

Если они не гарантированы для сортировки, я поместил бы каждый из них в HashSet, а затем вы можете использовать метод SetavaAll в java.

Редактировать: Как указал Томман, содержит всех () в конечном итоге полагается на равно (). Таким образом, чтобы проверить запросы на вопрос без учета регистра, у вас есть два варианта:

1) Пропускать или опускать строки при вставке в наборы. На мой взгляд, я не в восторге от этого метода, так как вы не только потеряете дубликаты записей, но и сбросите записи, дифференцированные по регистру. И поэтому эти списки выглядят равными друг другу:


String a [] = {"one","one","one", "Two"};
String b [] = {"One", Two"};

2) Другой вариант - поместить строки в объекты-держатели, которые переопределяют equals (), сравнивая без учета регистра.

0 голосов
/ 10 марта 2010

отметьте это во вложенных циклах, если вы хотите пользовательское сравнение. или если у вас большие наборы данных, может быть дешевле сначала отсортировать массивы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...