【问题标题】:Enumerating sliced array using original indices使用原始索引枚举切片数组
【发布时间】:2022-01-11 10:51:26
【问题描述】:

我需要对数组进行切片并枚举值,但我还需要对原始索引的引用,因为我正在执行异步操作,完成后需要将其映射回原始数组中的原始索引。

const array = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge'];
const slicedArray = array.slice(0, 3).map((v, i) => ({ v, i }));
// Returns: [{ "v": "foo", "i": 0 }, { "v": "bar", "i": 1 }, { "v": "baz", "i": 2 }]
// Required: [{ "v": "foo", "i": 0 }, { "v": "bar", "i": 1 }, { "v": "baz", "i": 2 }]
const slicedArray2 = array.slice(3, 6).map((v, i) => ({ v, i }));
// Returns: [{ "v": "qux", "i": 0 }, { "v": "quux", "i": 1 }, { "v": "corge", "i": 2 }]
// Required: [{ "v": "qux", "i": 3 }, { "v": "quux", "i": 4 }, { "v": "corge", "i": 5 }]

我怎样才能做到这一点?

【问题讨论】:

  • 首先映射 then 切片,如果您想要原始索引。或者给索引添加一个偏移量。
  • 或许,你只需要等待一堆promise并行解决?为此,请使用Promise.all
  • @DimaParzhitsky 是的,我使用的是Promise.allSettled,但我不知道原始索引,因为 slice 总是会重置它,对吗? @VLAZ 不太理想,原来的数组挺大的。
  • 是的,切片“重置”索引,因为它只是创建一个新数组。但是,Promise.allSettled() 不会改变项目的顺序。如果你这样做Promise.allSettled(foo(arr.slice(0, 3)), foo(arr.slice(3, 6))),你会得到两个数组,其中第一个对应索引 0-2,第二个对应索引 3-5。将结果与原始结果相匹配应该不难。您可以将所有结果和.concat() 抓取到一个与原始结果匹配的数组中(例如,也可以覆盖它)。

标签: javascript arrays slice


【解决方案1】:

切片中的项目的索引总是恰好小于原始数组中的startIndex:

slice(0, 3) -> [0, 1, 2] -> [0 - 0, 1 - 0, 2 - 0]
slice(3, 6) -> [0, 1, 2] -> [3 - 3, 4 - 3, 5 - 3]
slice(n, …) -> [0, 1, …] -> [n + 0 - n, n + 1 - n, n + 2 - n, …]

所以,只需在后面添加 startIndex 就可以了:

/**
 * @template Item
 * @param {Item[]} items
 * @param {number} startIndex
 * @param {number} [endIndex]
 * @returns {Array<{ item: Item; index: number }>}
 */
function slice(items, startIndex, endIndex = items.length) {
    return items.slice(startIndex, endIndex).map((item, index) => ({
        item,
        index: index + startIndex,
    }));
}

function slice(items, startIndex, endIndex = items.length) {
  return items.slice(startIndex, endIndex).map((item, index) => ({
    item,
      index: index + startIndex,
  }));
}

const letters = [ ...'abcdefghijklmnopqrstuvwxyz' ];

console.log(slice(letters, 0, 3));
console.log(slice(letters, 3, 6));
console.log(slice(letters, 6, 9));

【讨论】:

    【解决方案2】:

    使用array.map()可以得到value和index的所有数组! 之后使用.slice()

    试试这个代码对你有帮助

     const array = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge'];
     const slicedArray2 = array.map((v, i) => ({ v, i })).slice(3, 6);
     console.log(slicedArray2, 'slicedArray2');
    

    【讨论】:

    • 这种方法在一般情况下是最好的,但 OP 拒绝了它,因为原始数组“非常大”
    【解决方案3】:

    我实际上更喜欢接受的答案,但记录另一个没有slice的解决方案

    const data = ['foo', 'bar', 'baz', 'qux', 'quux', 'corge'];
    
    const slice = (items, startIndex, endIndex = items.length) => {
      return items.reduce((acc, v, i) => {
        if (i >= startIndex && i < endIndex )
          acc.push({ v, i })
        return acc;
      }, []);
    }
    
    console.log(slice(data, 0, 3));
    console.log(slice(data, 3));
    .as-console-wrapper{min-height: 100%!important; top: 0}

    【讨论】:

      猜你喜欢
      • 2015-12-17
      • 2011-12-31
      • 2021-04-18
      • 2013-12-06
      • 2010-09-29
      • 1970-01-01
      • 1970-01-01
      • 2010-10-01
      • 2014-06-03
      相关资源
      最近更新 更多