-1

From the answer of Why does a string index in an array not increase the 'length'?, I found out that arrays can have both value and properties.

For example in the following code:

var array = [];
array['test1'] = 'property 1';
array['test2'] = 'property 1';
array[0] = 'value 1';
array[1] = 'value 2';

Second and third line create property.

Fourth and fifth line create value.

I can get the values using:

array.forEach((value) => {
    console.log(value);
});

How can I get only the properties?

Ahmad Ismail
  • 11,636
  • 6
  • 52
  • 87
  • 2
    Why would you do that? Thats not how you should use Arrays. Just use an Object, with an array for the values and then you can set any other property you'd like. – 0stone0 May 25 '23 at 15:19

3 Answers3

3

Second and third line create property.

Fourth and fifth line create value.

No. All of those lines create a property and assigns a value to it.

The only difference is that some of those property names are integers.

How can I get only the properties?

If you want to use properties that are not numbers then do not use an array.

The purpose of an array is to store a set of values in an order. It does this using numeric property names. It has lots of special features specifically for handling numeric property names.

Use a regular object instead. You can convert it to an array you are iterate over with Object.entries, and filter out selected properties based on their name if you like.

const object = {};
object['test1'] = 'property 1';
object['test2'] = 'property 1';
object[0] = 'value 1';
object[1] = 'value 2';

const logger = ([name, value]) => console.log(`${name} is ${value}`);

Object.entries(object).forEach(logger);

console.log("-------");

Object.entries(object).filter(([name]) => !/^\d+$/.test(name)).forEach(logger);
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • I wanted **only properties**. – Ahmad Ismail May 25 '23 at 15:22
  • @AhmadIsmail — I refer you to the first paragraph of this answer (not counting the quote from the question at the top) and also the last half of the last sentence of this answer (not counting the example code at the end). – Quentin May 25 '23 at 15:23
0

You can use it

var array = [];
array['test1'] = 'property 1';
array['test2'] = 'property 1';
array[0] = 'value 1';
array[1] = 'value 2';

Object.keys(array).forEach((key)=>{
  if(isNaN(+key)){
    console.log(array[key])
  }
})
Zsolt Meszaros
  • 21,961
  • 19
  • 54
  • 57
voccer
  • 24
  • 3
  • This fails if `key` is a float-like string (e.g. `a[1.5] = 'float'`) or a string representing `Infinity`/`-Infinity` (e.g. `a[- + - - + -Infinity] = 42`). – InSync May 25 '23 at 15:21
  • Why did you use `+` before `key`? – Ahmad Ismail May 25 '23 at 15:30
  • 1
    @AhmadIsmail The `+` unary operator converts its operand to a number, which is not really necessary since `isNaN()` already covered that. – InSync May 25 '23 at 15:32
0

You can use a couple of conditions to filter out those you don't need:

function* nonNumericProperties(object) {
  for (const key in object) {
    // Own keys only.
    if (!Object.hasOwn(object, key)) {
      continue;
    }
    
    // Filter out non-negative integers.
    // Keys like '001' are valid.
    if (/^(?:[1-9]\d*|0)$/.test(key)) {
      
      // An array's size is capped at 2 ** 32 - 2,
      // which means integers greater than that
      // are not indices.
      // https://stackoverflow.com/a/6155063
      const parsedKey = Number(key);
      if (parsedKey <= 2 ** 32 - 2) {
        continue;
      }
    }
    
    yield [key, object[key]];
  }
}

Try it:

console.config({ maximize: true });

function* nonNumericProperties(object) {
  for (const key in object) {
    if (
      !Object.hasOwn(object, key) ||
      (/^(?:[1-9]\d*|0)$/.test(key) && +key <= 2 ** 32 - 2)
    ) {
      continue;
    }
    
    yield [key, object[key]];
  }
}

const array = [0, 1, 2];
array.property = 'property';
array[Infinity] = Infinity;
array[1.5] = 'float';
array[2e-14] = 'float + scientific notation';
array['00234'] = '0-padded';
array[NaN] = NaN;
array[2 ** 32] = 2 ** 32;

for (const [key, value] of nonNumericProperties(array)) {
  console.log(key, value);
}
<script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
InSync
  • 4,851
  • 4
  • 8
  • 30