0

This is my attempt at writing a JavaScript program to sort the contents of the data array based on data classification. The final data should be stored as the sortedData object which should have arrays assigned to its properties. Each property is an array of items that meet the data classification guidelines. However, my program doesn't seem to be working. Can someone please explain what's going on?

let data = [
    538, 922, "725", false, 733, 170, 294, "336", false, "538", 
    79, 390, true, "816", "50", 920, "845", "728", "133", 
    "468", false, true, 520, 747, false, "540", true, true, 
    "262", 625, "614", 316, "978", "865", "506", 552, 187, 
    "444", 676, 544, 840, 691, "50", 21, "926", "10", 37, 
    "704", "36", 978, 830, 438, true, "713", 497, "371", 243, 
    638, 454, 291, "185", "941", "581", 336, 458, "585", false, 
    870, "639", "360", 599, "644", "767", 878, "646", 117, 
    "933", 48, 934, "155", "749", 808, 922, 94, "360", "395", 
    false, 407, true, false, "97", "233", 70, "609", false, 
    false, "13", "698", 797, "789"
];

let sortedData = {
    stringArray: 0,
    booleanArray: 0,
    numberArray: 0,
}

for (let i = 0; i < data.length; i++) {
    if (typeof data[i] == 'string') {
        sortedData.stringArray[i] = data[i];
    } else if (typeof data[i] == 'boolean') {
        sortedData.booleanArray[i] = data[i];
    } else if (typeof data[i] == 'number') {
        sortedData.numberArray[i] = data[i];
    }
}
Ivar
  • 6,138
  • 12
  • 49
  • 61
Ken Ely
  • 191
  • 7

4 Answers4

3

You are assigning 0 to stringArray, booleanArray and numberArray. A 0 isn't an array, so you can't add values to it like that. (Assigning values to a primitive type is a noop.)

Assign an array to those values and use .push() on them to add values to those arrays. (Using [i] will leave gaps in your array, because each iteration i will be incremented but only one of the arrays will get a value at that index, leaving the other two blank.)

let data = [
  538, 922, "725", false, 733, 170, 294, "336", false, "538", 
  79, 390, true, "816", "50", 920, "845", "728", "133", 
  "468", false, true, 520, 747, false, "540", true, true, 
  "262", 625, "614", 316, "978", "865", "506", 552, 187, 
  "444", 676, 544, 840, 691, "50", 21, "926", "10", 37, 
  "704", "36", 978, 830, 438, true, "713", 497, "371", 243, 
  638, 454, 291, "185", "941", "581", 336, 458, "585", false, 
  870, "639", "360", 599, "644", "767", 878, "646", 117, 
  "933", 48, 934, "155", "749", 808, 922, 94, "360", "395", 
  false, 407, true, false, "97", "233", 70, "609", false, 
  false, "13", "698", 797, "789"
];

let sortedData = {
  stringArray: [],
  booleanArray: [],
  numberArray: [],
}

for (let i = 0; i < data.length; i++) {
  if (typeof data[i] == 'string') {
    sortedData.stringArray.push(data[i]);
  } else if (typeof data[i] == 'boolean') {
    sortedData.booleanArray.push(data[i]);
  } else if (typeof data[i] == 'number') {
    sortedData.numberArray.push(data[i]);
  }
}

console.log(sortedData);
Ivar
  • 6,138
  • 12
  • 49
  • 61
3

explainations at the code.

// data is array with mixed data type
let data = [
  123, 12.3, "123", [1,2,3], {'1':[2,3]}, true, false, null, undefined 
];

// sfxName  : extra suffix for 'grpName'
// grpName  : type + sfxName
// the output key will be > numberArray, booleanArray etc...
let 
sorted = {},
sfxName = '_Array';


for( let n of data ){
  const grpName = (n === null) ? n + sfxName : typeof n + sfxName;
  if (!sorted[grpName]) sorted[grpName] = [];
  sorted[grpName].push(n);
}

console.log( sorted );
Hanna Rose
  • 412
  • 2
  • 9
  • The problem with this approach is that it will throw an error if `data` contains any value whose type is not included in `sortedData`. For example, if data contains an `undefined` item, you will get the error `Uncaught TypeError: Cannot read property 'push' of undefined` because `sortedData.undefinedArray` does not exist. – secan Aug 03 '21 at 10:06
  • you can simply add this, before push. it will check the existence of target push, if not exist this code will add new : if( !sortedData[typeof(i)+'Array'] ){ sortedData[typeof(i)+'Array'] = []; } – Hanna Rose Aug 03 '21 at 10:34
  • i just edited my code. Let me know if something doesn't work correctly. thanks – Hanna Rose Aug 03 '21 at 10:44
  • @HannaRose ... [`typeof`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) is an operator, there is no need for parenthesis around the `i`. Also, since you now switched to a generic approach, there has to be an additional check for the `null` value ... remember `typeof null` equals `'object'`. Maybe you also assign the result of `typeof(i)+'Array'` temporarily to a variable, thus the computation of this string value happens only once. – Peter Seliger Aug 03 '21 at 11:13
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof – Hanna Rose Aug 03 '21 at 21:03
2

You can do it using Array.prototype.reduce:

let data = [
  538, 922, "725", false, 733, 170, 294, "336", false, "538",
  79, 390, true, "816", "50", 920, "845", "728", "133",
  "468", false, true, 520, 747, false, "540", true, true,
  "262", 625, "614", 316, "978", "865", "506", 552, 187,
  "444", 676, 544, 840, 691, "50", 21, "926", "10", 37,
  "704", "36", 978, 830, 438, true, "713", 497, "371", 243,
  638, 454, 291, "185", "941", "581", 336, 458, "585", false,
  870, "639", "360", 599, "644", "767", 878, "646", 117,
  "933", 48, 934, "155", "749", 808, 922, 94, "360", "395",
  false, 407, true, false, "97", "233", 70, "609", false,
  false, "13", "698", 797, "789", null, {}, undefined, null, [], x => x * 2
];

const sortedData = data.reduce((outObj, item) => {
  const key = item === null // this check is needed because, for historical reasons `typeof(null)` returns 'object' instead of 'null'
    ? 'nullArray'
    : typeof(item) + 'Array';
  
  if (outObj.hasOwnProperty(key)) {
    // if the object already has a key for that data type, push the item in the existing array
    outObj[key].push(item);
  } else {
    // otherwise create the new key and add the item to it
    outObj[key] = [item];
  }
  
  return outObj;
}, {});

// test
console.log(sortedData);

This approach has the advantage that you do not need to know in advance how many data types are present in the original array and what they are, as it will automatically create a new key as soon as it encounters a new data type.

[EDIT] Just to avoid any misunderstanding: when I say "this approach" I mean the approach of dynamically creating the object keys, which is something you can do regardless of whether you use a simple for loop or Array.prototype.reduce(). ;)

secan
  • 2,622
  • 1
  • 7
  • 24
0

Change the values of zero to an array like this:

let sortedData = {
    stringArray: [],
    booleanArray: [],
    numberArray: [],
}
//            set value on array item
//                      ||
//                      \/
 sortedData.stringArray[i] === 'something'
Steve Tomlin
  • 3,391
  • 3
  • 31
  • 63