简体   繁体   中英

Only Push onto array once versus pushing to array every time condition is met

I am importing excel files that contain customer orders like so

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)
  }

The way the excel files are imported an object of arrays where each array is a row of the excel sheet.

In the following code snippet, I am searching for items in a column to identify the column in an excel sheet that has the shoe brands requested by a customer in the code

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])
        }
      }
      }

    }

this works in that it pushes all of the items in the relevant column into the array but it does so every time the conditions are met and as such the same column is pushed into the array a bunch of times as opposed to only pushing the column items once. Is there a way maybe using the % or other function so that the column is only pushed into the array one time? So if I had a customer sheet come in like this:

示例订单

I would want the array to have [Nike, Adidas, Puma, Puma, Asics, Nike]

One way is to use a Set. You probably don't want to check if it is in the array before you add it, because then you may have O(n²) time complexity, which can be undesirable.

You can add it to a set, and return as a set, or if needed, return as an array:

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

I would have just used console.log(mySet) but for some reason StackOverflow can't print out its value (unlike Node.js or Chrome). But then it shows how to convert the set back to an array. You can also use Array.from(mySet) .

So in your code, you probably have:

this.manufactSet = new Set();

and in the loop:

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

and after the loop, you can set it back to an array:

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

But I don't quite get your code:

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])
        }

Why when you found Adidas , then you push everything into the result? Shouldn't you do:

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])

?

Is this.data[i] a string that might have "Cool Adidas NMD hard to find"... and once you find the "location" of Adidas , why do you just push that character into the result?

Don't you want to push the whole string into the result?

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])

So after checking what data[i] is and what you would like to do, seems like this is what you want to do:

Note that you mentioned you actually want the manufacturer to appear more than once, like ["Adidas", "Adidas", "Nike", "Puma", "Nike"] , so I won't use a set as the result below:

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]);
}

Actually, there is a better way to write it now in 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]);
}

I think I see what you mean by "pushing" every time instead of once. You mean if you see Adidas , you push the whole column values to the array, and the next row, you see Nike , and you push the whole column values to the array again. You could have just returned if you put that in a function. So once you see Adidas , then just push all values in that column to the array and return from the function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM