JavaScript 如何使用无突变的递归从嵌套对象构建数组

JavaScript how to build array from nested Object using recursion without mutation

interface SubscriptionParams {
  selectedProduct?: SubscriptionSelectedProduct;
}

interface SubscriptionSelectedProduct {
  productId?: string;
  pricingId?: string;
  childProduct?: SubscriptionSelectedProduct;
}

function getChildIdRecursively(product: SubscriptionSelectedProduct, ids: string[]) {
  if (product) {
    ids.push(product.productId!);
    product.childProduct && getChildIdRecursively(product.childProduct, ids);
  }
}

function subscriptionProductsIds(subscription: SubscriptionParams): string[] {
  let ids: string[] = [subscription.selectedProduct?.productId!];
  if (subscription.selectedProduct?.childProduct) {
    getChildIdRecursively(subscription.selectedProduct?.childProduct, ids);
  }

  return ids;
}

如何在不改变的情况下进行递归,现在我正在改变 ids 数组。 我想遵循函数式编程原则

我会避免创建大量不必要的中间数组,但每个数组都有自己的。使这个“不可变”就像从 getChildIdRecursively 返回一个新数组一样简单。此外,由于您基本上是在复制 subscriptionProductsIds 中的逻辑,因此您可以删除它。

function getChildIdRecursively(product: SubscriptionSelectedProduct) {
  if (product) {
    let ids: string[] = [product.productId!];
    if (product.childProduct) {
      ids = ids.concat(getChildIdRecursively(product.childProduct));
    }
    return ids;
  }
  return [];
}

function subscriptionProductsIds(subscription: SubscriptionParams): string[] {
  return getChildIdRecursively(subscription.selectedProduct)
}

我认为您可以通过利用树遍历恕我直言来解决这个问题。

const collectIds = (node) => {
  const { id, children = [] } = node;
  
  // const children = [product.childProduct] in your specific case
  const ids = children.flatMap(collectIds);
  
  return [id, ...ids];
};


const product = {
  id: 'L1',
  children: [
    { id: 'L1.1' },
    { 
      id: 'L1.2', 
      children: [
        { id: 'L1.2.1', },
        { id: 'L1.2.2', },
        { id: 'L1.2.3', },
        { id: 'L1.2.4', },
        { id: 'L1.2.5', },
      ],
    },
  ],
};

console.log(
  collectIds(product),
);