注意能够从List <int []>获得Distinct int []

时间:2019-06-13 05:12:53

标签: java-8

我试图获取具有唯一int []的独特列表,但我仍在重复。

            Microsoft.Office.Interop.Excel._Application app = new Microsoft.Office.Interop.Excel.Application();
            Microsoft.Office.Interop.Excel._Workbook workbook = app.Workbooks.Add(Type.Missing);
            Microsoft.Office.Interop.Excel._Worksheet worksheet = null;

            worksheet = workbook.Sheets["Sheet1"];
            worksheet = workbook.ActiveSheet;
            worksheet.Name = "Exported from gridview";
            for (int i = 1; i < dataGridView1.Columns.Count + 1; i++)
            {
                worksheet.Cells[1, i] = dataGridView1.Columns[i - 1].HeaderText;
            }

            for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
            {
                for (int j = 0; j < dataGridView1.Columns.Count; j++)
                {
                    worksheet.Cells[i + 2, j + 1] = dataGridView1.Rows[i].Cells[j].Value.ToString();
                }
            }
            var saveFileDialoge = new SaveFileDialog();
            saveFileDialoge.FileName = "output";
            saveFileDialoge.DefaultExt = ".xlsx";
            if (saveFileDialoge.ShowDialog() == DialogResult.OK)
            {
                workbook.SaveAs(saveFileDialoge.FileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
                app.Visible = true;

从int []的组合列表中获取所需元素的逻辑是数组中的数字应连续且相差1。

例如:{2,3,4}

但是在我的最终列表中,{2,3,4}即将出现3次了,这是显而易见的。我想对{2,3,4}进行1次3次的出现。所以我写了以下逻辑。仍然有许多元素以{4,5,6}的连续形式出现,我希望它们也只被计数一次。

List<Integer> set1 = Arrays.asList(2, 3, 4, 5, 10, 4, 5, 6, 4);
List<Integer> count = new ArrayList<>();
List<int[]> combination = set1.stream().flatMap(i -> set1.stream().
            flatMap(j -> set1.stream().map(k -> new int[] { i, j, k }))) 
                                      .distinct().collect(Collectors.toList());

我得到的唯一元素为15,但应该为3。

  

我的最终 List<int[]> combination1 = combination.stream().distinct().collect(Collectors.toList()); combination1.stream().filter(i -> Collections.frequency(combination, i) == 1).forEach(s -> { if (s[1] - s[0] == 1 && s[2] - s[1] == 1 && s[2] - s[0] == 2) { count.add(1); } else { count.add(0); } }); System.out.println(count.stream().mapToInt(Integer::intValue).sum()); 应该只包含:{2,3,4},{3,4,5},{4,5,6}   因此计数应该为三。

3 个答案:

答案 0 :(得分:3)

这是distinct()文档的第一行:

  

返回由该流的不同元素(根据Object.equals(Object) 组成)的流。

现在,因为您正在Stream<int[]>上运行它,所以当两个int数组具有相同的内容时,int[].equals将必须返回true。但事实并非如此(请参阅this)。您可以通过在distinct()之前使用列表,然后在之后进行映射来解决此问题(此处使用Integer[],但是int[]需要一个不同的映射):

List<Integer[]> combination = set1.stream()
    .flatMap(i -> set1.stream()
                      .flatMap(j -> set1.stream().map(k -> Arrays.asList(i, j, k))))
    .distinct()
    .map(l -> l.toArray(new Integer[0]))
    .collect(Collectors.toList());

答案 1 :(得分:3)

尽管@ernest_k提到了解决方案的基本问题,但我认为您可以通过简单的方式来解决。

首先从set1个元素创建地图。

Map<Integer,Integer> map = set1.stream()
                      .collect(Collectors
                                .toMap(Function.identity(),Function.identity(),(v1,v2)->v1));
  

{2 = 2,3 = 3,4 = 4,5 = 5,6 = 6,10 = 10}

然后通过循环映射值可以创建连续的数组。

List<Integer[]> combination = map.values()
            .stream()
            .filter(item -> map.containsKey(item + 1) && map.containsKey(item + 2))
            .map(item -> new Integer[] {item, item + 1, item + 2})
            .collect(Collectors.toList());

@Holger评论使用set会更简单。

Set<Integer> set = new HashSet<>(set1);
List<Integer[]> combination = set.stream()
            .filter(item -> set.contains(item + 1) && set.contains(item + 2))
            .map(item -> new Integer[] {item, item + 1, item + 2})
            .collect(Collectors.toList());

答案 2 :(得分:3)

this answer中所述,2019-06-12 00:00:00数组不具有int[]的require相等。但是,IntBuffer可以包装distinct()数组并提供基于值的相等性。因此,您可以使用序列int[]获得不同的数组,以包装数组,消除重复并拆开数组。

但是,该问题是完全不必要的步骤的一部分,因为您没有专注于要解决的实际问题。

要获取所有具有连续值的元组,只需使用

map(IntBuffer::wrap).distinct().map(IntBuffer::array)

不是创建所有值的729个组合,而是消除冗余组合,然后消除不匹配的组合,它首先只生成四个可能的升序组合。然后,将其过滤掉,只接受连续数字的序列。

因此最后一条语句将打印

List<Integer> set1 = Arrays.asList(2, 3, 4, 5, 10, 4, 5, 6, 4);

int[] ascending = set1.stream().mapToInt(Integer::intValue).sorted().distinct().toArray();

List<int[]> combination = IntStream.rangeClosed(0, ascending.length - 3)
    .mapToObj(ix -> Arrays.copyOfRange(ascending, ix, ix + 3))
    .filter(a -> a[0] + 1 == a[1] && a[1] + 1 == a[2])
    .collect(Collectors.toList());

combination.forEach(a -> System.out.println(Arrays.toString(a)));