1. 程式人生 > 其它 >多層陣列笛卡爾積

多層陣列笛卡爾積

技術標籤:java

遇到一個問題,要求不定長度多維陣列的笛卡爾積集合,找了和很多資料都是二維的,然後我在二維基礎上,寫了個多維的

利用雙層陣列笛卡爾積方法,處理多層陣列的笛卡爾積,

該例子以long 型別陣列為例

 @org.junit.Test
    public void testDecartes() {
//       List<List<String>> listLevel2 = Lists.newArrayList(Lists.newArrayList("a","b","c"),Lists.newArrayList("d","e","f"));
//        List<List<String>> result = CollectionUtil.decartes(listLevel2);
//        logger.info("result:{}",result);

        List<List<String>> listLevel2 = new ArrayList<>();
        listLevel2.add(Lists.newArrayList("1","2","3"));
        listLevel2.add(Lists.newArrayList("4","5","6"));
        listLevel2.add(Lists.newArrayList("7","8","9"));

        List<String> resultFinal = listLevel2.get(0);

        for(int i =1 ;i < listLevel2.size();i++){

            List<List<String>> currResult = CollectionUtil.decartes(Lists.newArrayList(resultFinal,listLevel2.get(i)));

            //currResult 轉換成逗號隔開一維list ,resultFinal 值更新
            resultFinal.clear();
            for(List<String> one : currResult){
                resultFinal.add(String.join(",",one));
            }
        }

        //List<String> 轉 List<List<Long>>
        List<List<Long>> finalResultLong = new ArrayList<>();
        resultFinal.forEach( one ->{
            finalResultLong.add(
            Arrays.stream(one.split(",")).map(oneStr->{
                return Long.parseLong(oneStr);
            }).collect(Collectors.toList())
            );
        });

        logger.info("finalResultLong:{}",finalResultLong);
    }

CollectionUtils:

// Copyright 2016 Leyantech Ltd. All Rights Reserved.

package com.leyantech.eci.pm.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author lxc, {@literal <[email protected]>}
 * @date 2020-06-10.
 */
public class CollectionUtil {

  /**
   * Check whether a given list is null or empty
   */
  public static boolean isNullOrEmpty(Collection<? extends Object> list) {
    return list == null || list.isEmpty();
  }


  /**
   * 計算笛卡兒積
   *
   * @param crossArgs a {@link java.util.List} object.
   * @param <T>       a T object.
   * @return a {@link java.util.List} object.
   */
  public static <T> List<List<T>> decartes(List<List<T>> crossArgs) {

    // 計算出笛卡爾積行數
    int rows = crossArgs.size() > 0 ? 1 : 0;

    for (List<T> data : crossArgs) {
      rows *= data.size();
    }

    // 笛卡爾積索引記錄
    int[] record = new int[crossArgs.size()];

    List<List<T>> results = new ArrayList<List<T>>();

    // 產生笛卡爾積
    for (int i = 0; i < rows; i++) {
      List<T> row = new ArrayList<T>();

      // 生成笛卡爾積的每組資料
      for (int index = 0; index < record.length; index++) {
        row.add(crossArgs.get(index).get(record[index]));
      }

      results.add(row);
      crossRecord(crossArgs, record, crossArgs.size() - 1);
    }

    return results;
  }

  /**
   * @param record
   * @param level
   */
  private static <T> void crossRecord(List<List<T>> sourceArgs, int[] record, int level) {
    record[level] = record[level] + 1;

    if (record[level] >= sourceArgs.get(level).size() && level > 0) {
      record[level] = 0;
      crossRecord(sourceArgs, record, level - 1);
    }
  }

}