繁体   English   中英

java-如何检查两个序列是否以某种顺序具有相同的值,(忽略重复项)

[英]How to check whether two sequences have the same values in some order, (ignoring duplicates) java

这是一个分为两部分的问题,第一个问题要求创建一种方法来检查两个序列是否具有相同顺序的相同值。

其次,我在问题上遇到的问题要求创建一种方法来检查两个序列是否以某种顺序具有相同的值,而忽略重复项,即序列1(1、4、9、16、9、7、4、9, 11)序列2(11、11、7、9、16、4、1)所以序列1仍与序列2相同,因为11、4和9是重复元素

因此,我添加了一个方法public boolean equals(Sequence other),该方法检查两个序列在​​相同顺序中是否具有相同的值,第1部分,但我现在需要做的是第2部分,检查两个序列是否以相同顺序具有相同的值,忽略重复项。

import java.util.Arrays;
public class Sequence {
    private int[] values;
    public Sequence(int size)
    {
        values = new int[size];
    }
    public void set(int i, int n)
    { 
        values[i] = n; 
    }
    public boolean equals(Sequence obj) 
    {
        if (this == obj)
        {
            return true;
        }
        if (obj == null)
        {
            return false;
        }
        if (getClass() != obj.getClass())
        {
            return false;
        }
        Sequence other = (Sequence) obj;
        if (!Arrays.equals(values, other.values))
        {
            return false;
        }
        return true;
    }
    public static void main(String args[]){
        Sequence s = new Sequence(5);
        Sequence s2 = new Sequence(5);// new Sequence(4)
        s.set(0, 1);
        s2.set(0, 1);
        System.out.println(s.equals(s2));//will print true      
    }
}

我有点困惑,我知道这是您检查重复项的方式,但这就是我所知道的,我真的不知道在这种情况下如何使用它或如何忽略重复项

for (int i = 0; i < values.length; i++) 
{ 
    for (int j = i + 1; j < other.length; j++) 
    { 
        if (values[i].equals(other[j]) ) {}
    }
}

较慢的方法是:遍历较小的数组,并针对每个值检查它是否包含在较大的数组中。 然后反过来...因此,没有任何其他“智能”,您需要进行n * m个比较。 时代2。

一个更复杂的解决方案:对两个数组进行排序。 然后开始轮流遍历两个数组(对两个数组进行排序时,无需重复迭代第二个数组即可确定它是否包含另一个数组中的值)。 然后,您只需要遍历两个数组一次(但是请注意:以某种交替的方式)。

我认为最简单的方法是:

  • 对两个数组排序
  • 获取数组的不同值。
  • 比较排序的唯一数组

通过@DodgyCodeException更新,事实证明在流中对数组进行排序更有效。

    int[] val1 = {1,1,4,9,16,9,7,4,9,11};
    int[] val2 = {11, 7, 9, 16, 7, 4, 1};

    //Compare should  be false
    System.out.println(Arrays.equals(val1, val2)); //false

    //Sort Array and get distinct Values
    //Assign to new int[] if you do not want to change the original arrays
    val1 = Arrays.stream(val1).sorted().distinct().toArray();
    val2 = Arrays.stream(val2).sorted().distinct().toArray();

    //Compare should be true
    System.out.println(Arrays.equals(val1, val2)); //true

这与Java的Set机制无关紧要。 只要为T类型正确实现了equalshashCode ,以下代码段将起作用:

private boolean equalWithDuplicates(T[] a, T[] b) {
    return new HashSet<>(Arrays.asList(a)).equals(new HashSet<>(Arrays.asList(b)));
}

但是,正如评论者所指出的那样, 此SO帖子似乎表明需要装箱原始数组以使解决方案起作用:

private boolean equalWithDuplicates(int[] a, int[] b) {
    Set<Integer> boxedA = Arrays.stream(a).boxed().collect(Collectors.toSet());
    Set<Integer> boxedB = Arrays.stream(b).boxed().collect(Collectors.toSet());
    return boxedA.equals(boxedB);
}

不确定您的意思,但是如果要删除重复项,最简单的方法是使用java.util.Set,例如java.util.HashSet。 此外,写一个equals(Sequence obj)方法可能被认为是不好的做法,因为它会使equals(Object obj)重载。您可能想覆盖该方法,然后将其重载。

我认为您的Sequence类可能看起来像这样。 EQUALS_IGNORE_ORDER_AND_DUPLICATES的主要思想只是将输入数据转换为数据,可以与已经创建的equal函数一起使用。

final class Sequence {

    private final int[] values;

    public Sequence(int size) {
        values = new int[size];
    }

    public void set(int i, int n) {
        values[i] = n;
    }

    public static final BiPredicate<Sequence, Sequence> EQUALS = (seq1, seq2) -> Arrays.equals(seq1.values, seq2.values);

    public static final BiPredicate<Sequence, Sequence> EQUALS_IGNORE_ORDER_AND_DUPLICATES = (seq1, seq2) -> {
        Set<Integer> set1 = seq1 != null ? Arrays.stream(seq1.values).boxed().collect(Collectors.toSet()) : Collections.emptySet();
        Set<Integer> set2 = seq2 != null ? Arrays.stream(seq2.values).boxed().collect(Collectors.toSet()) : Collections.emptySet();
        return set1.equals(set2);
    };

}

测试:

int[] val1 = { 1, 1, 4, 9, 16, 9, 7, 4, 9, 11 };
int[] val2 = { 11, 7, 9, 16, 7, 4, 1 };

Sequence seq1 = new Sequence(val1.length);
Sequence seq2 = new Sequence(val2.length);

for (int i = 0; i < val1.length; i++)
    seq1.set(i, val1[i]);

for (int i = 0; i < val2.length; i++)
    seq2.set(i, val2[i]);

boolean res1 = Sequence.EQUALS.test(seq1, seq2);    // false
boolean res2 = Sequence.EQUALS_IGNORE_ORDER_AND_DUPLICATES.test(seq1, seq2);   // true

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM