【问题标题】:Only Push onto array once versus pushing to array every time condition is met只推送一次数组,而不是每次满足条件时推送到数组
【发布时间】:2020-01-12 20:23:38
【问题描述】:

我正在导入包含这样的客户订单的 excel 文件

onFileChange(event: any) {
    const inputFile: DataTransfer = <DataTransfer>(event.target); 
    const fileReader: FileReader = new FileReader();
    fileReader.onload = (event: any) => {
      const binaryString: string = event.target.result;
      const workBook: XLSX.WorkBook = XLSX.read(binaryString, { type: 'binary', sheetStubs: true}); 
      /* sheetstubs true supposedly shows empty cells but isn't */
      console.log(typeof binaryString)

      const workSheetName: string = workBook.SheetNames[0];
      console.log(workSheetName)
      const workSheet: XLSX.WorkSheet = workBook.Sheets[workSheetName];

      this.data = <Array>(XLSX.utils.sheet_to_json(workSheet, { header: 1, blankrows: true }));


    };
    fileReader.readAsBinaryString(inputFile.files[0]);
    console.log(this.data)
  }

excel文件导入数组对象的方式,其中每个数组是excel表的一行。

在下面的代码 sn-p 中,我正在搜索列中的项目以识别 Excel 表中包含客户在代码中请求的鞋品牌的列

for (var i=0; i<this.data.length; i++){
      if (this.data[i].indexOf('Adidas') != -1) {
        var manIndex = this.data[i].indexOf('Adidas')
        for( var j = 0; j<this.data.length; j++){
          this.manufactArray.push(this.data[j][manIndex])
        }

      }
      else if (this.data[i].indexOf('Puma') != -1) {
        var manIndex = this.data[i].indexOf('Puma')
        for (var j=0; j<this.data.length; j++) {
          this.manufactArray.push(this.data[j][manIndex])
        }
      }
      else if (this.data[i].indexOf('Nike') != -1) {
        var manIndex = this.data[i].indexOf('Nike')
        for(var j = 0; j<this.data.length; j++){
          this.manufactArray.push(this.data[j][manIndex])
        }
      }
      }

    }

它的工作原理是将相关列中的所有项目推送到数组中,但每次满足条件时都会这样做,因此同一列会被推送到数组中很多次,而不是仅推送列项目一次。有没有办法使用% 或其他函数,以便该列只被推入数组一次?因此,如果我有这样的客户表进来:

我希望数组有[Nike, Adidas, Puma, Puma, Asics, Nike]

【问题讨论】:

    标签: javascript arrays typescript algorithm


    【解决方案1】:

    一种方法是使用 Set。您可能不想在添加之前检查它是否在数组中,因为那样您可能有 O(n²) 时间复杂度,这可能是不可取的。

    您可以将其添加到集合中,并作为集合返回,或者如果需要,作为数组返回:

    const mySet = new Set();
    
    mySet.add(123);
    console.log([...mySet]);
    
    mySet.add("hello world");
    console.log([...mySet]);
    
    mySet.add(123);
    console.log([...mySet]);

    我会使用console.log(mySet),但由于某种原因,StackOverflow 无法打印出它的值(与 Node.js 或 Chrome 不同)。但随后它显示了如何将集合转换回数组。你也可以使用Array.from(mySet)

    所以在你的代码中,你可能有:

    this.manufactSet = new Set();
    

    在循环中:

    this.manufactSet.add(this.data[j][manIndex]);
    

    在循环之后,您可以将其设置回数组:

    this.manufactArray = [...this.manufactSet];
    

    但我不太明白你的代码:

    for (var i=0; i<this.data.length; i++){
          if (this.data[i].indexOf('Adidas') != -1) {
            var manIndex = this.data[i].indexOf('Adidas')
            for( var j = 0; j<this.data.length; j++){
              this.manufactArray.push(this.data[j][manIndex])
            }
    

    为什么当你找到Adidas,然后你把everything推到结果中? 你不应该这样做吗:

    for (var i=0; i<this.data.length; i++){
          if (this.data[i].indexOf('Adidas') != -1) {
            var manIndex = this.data[i].indexOf('Adidas')
            this.manufactArray.push(this.data[i][manIndex])
    

    ?

    this.data[i] 是一个可能包含“Cool Adidas NMD hard to find”的字符串吗?一旦你找到了Adidas 的“位置”,你为什么要把那个字符推到结果中?

    您不想将整个字符串推入结果中吗?

    for (var i=0; i<this.data.length; i++){
          if (this.data[i].indexOf('Adidas') != -1) {
            var manIndex = this.data[i].indexOf('Adidas')
            this.manufactArray.push(this.data[i])
    

    所以在检查了 data[i] 是什么以及你想要做什么之后,看起来这就是你想要做的:

    请注意,您提到您实际上希望制造商出现不止一次,例如["Adidas", "Adidas", "Nike", "Puma", "Nike"],所以我不会使用如下结果的集合:

    const someManufacturers = new Set(['Adidas', 'Puma', 'Nike']);
    
    function getColumnNumber() {
      for (var i = 0; i < this.data.length; i++) {
        for (var j = 0; j < this.data[i].length; j++) {
          if (someManufacturers.has(this.data[i][j])) return j;
        }
      }
    }
    var manufacturerColumnNumber = getColumnNumber();
    
    for (var i = 0; i < this.data.length; i++) {
      this.manufactArray.push(this.data[i][manufacturerColumnNumber]);
    }
    

    其实现在在 ES6 中有更好的写法:

    const someManufacturers = new Set(['Adidas', 'Puma', 'Nike']);
    
    function getColumnNumber() {
      for (const row of this.data) {
        for (let i = 0; i < row.length; i++) {
          if (someManufacturers.has(row[i])) return i;
        }
      }
    }
    var manufacturerColumnNumber = getColumnNumber();
    
    for (const row of this.data) {
      this.manufactArray.push(row[manufacturerColumnNumber]);
    }
    

    我想我明白你所说的每次“推动”而不是一次的意思。您的意思是,如果您看到Adidas,则将整个列值推送到数组中,而下一行,您会看到Nike,然后再次将整个列值推送到数组中。如果你把它放在一个函数中,你可能刚刚返回。因此,一旦您看到 Adidas,只需将该列中的所有值推送到数组并从函数返回。

    【讨论】:

    • 你能加入一个sn-p吗?
    • 嗯,这不一定能回答我的问题,我可以在列中包含重复的品牌,但我不希望在算法识别出“常见”品牌后多次推送整个列我希望将整列复制到数组中
    • 哦,我知道问题是什么,我会更新我的问题
    • 所以基本上我是从使用xlsx库导入它们的excel表中获取这些信息的
    • 那么最终理想的结果是什么? [ ["Adidas", "Adidas", "Nike", "Adidas", "Asics"], ["Nike", "Nike", "Puma"], ["Asics", "Asics"] ] 之类的东西?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 2012-01-27
    • 1970-01-01
    • 2016-09-25
    相关资源
    最近更新 更多