user3078775
user3078775

Reputation: 87

Find array element based on it's value (JavaScript)

I have the following array:

[
 0 [product_id, title, description]
 1 [1234, apple, this is just apple]
 2 [2345, pineapple, this is not just apple]
]

This array is long and product_id's can vary by a lot. I need to select an element based on it's product_id and update it's title and description.

Is there a way to do it without a for loop (such as for -> if product_id = id -> do something), since I will end up with n^2?

Thank you for your time.

Upvotes: 0

Views: 70

Answers (3)

yangli-io
yangli-io

Reputation: 17334

  • Assumption: product_id is unique

For an array there is no other way but to loop through it all. You should consider changing your datamodel into a JSON then it will become much easier.

In your example

var products = [
 0 [product_id, title, description]
 1 [1234, apple, this is just apple]
 2 [2345, pineapple, this is not just apple]
]

becomes

var products = {
    product_id: [product_id, title, description],
    1234: [1234, apple, this is just apple],
    2345: [2345, pineapple, this is not just apple]
}

Now you can simply say

var select_1234 = products[1234];

to get the product of 1234.

If you must stick with the array and you need to find products multiple times, consider doing a transform at the beginning of your app to change it into json. As such you have indexed your data and now you can again call

products[1234]

EDIT

Alternatively, you can create json data to link to your array for example

var productsIndex = {
    product_id: 0,
    1234: 1,
    2345: 2
}

This links to the position of the array so now you can call

var find = productsIndex[1234];
var select_1234 = products[find]; //This is the original array.

As an extra, consider using async transformations to transform the data so it does not freeze up any UI. This can be done using a recursive setTimeout with 0 seconds

var products = {
    product_id: [product_id, title, description],
    1234: [1234, apple, this is just apple],
    2345: [2345, pineapple, this is not just apple]
}

var productsIndex = {}

function recursiveTransform(val){
    setTimeout(function(){
        productsIndex[products[val].[0]] = val; //products[val].[0] is the product id of each array element
        if (val != products.length -1) recursiveTransform(val+1);
    }, 0)
}

recursiveTransform(0);

By doing this, you will not freeze up your ui or any other operation that might need to be run during the process

  • I haven't tested the code but it should give you an idea

Upvotes: 1

Dylan Watt
Dylan Watt

Reputation: 3387

There's no way to lookup like you want. You'll need to create a map. That map can either replace your initial array in your data, if it makes sense, or you can just generate a lookup map that you refer to later.

Luckily if you set fooarray[0] = bar;foomap['uuid'] = bar;, you can update bar via either data structure eg fooarray[0][1] = 'new title' or foomap['uuid'][1] = 'new title' and it will update in both structures, because it's passed by reference.

edit building on @YangLi:

var products = {
    product_id: [product_id, title, description],
    1234: [1234, apple, this is just apple],
    2345: [2345, pineapple, this is not just apple]
}

var productsIndex = {}

function recursiveTransform(val){
    setTimeout(function(){
        productsIndex[products[val].[0]] = products[val];
        if (val != products.length -1) recursiveTransform(val+1);
    }, 0)
}

recursiveTransform(0);

Upvotes: 0

Sebastian Simon
Sebastian Simon

Reputation: 19475

Use Array.prototype.find or Array.prototype.findIndex:

[
  [2439, 'title', 'description'],
  [1234, 'apple', 'this is just apple'],
  [2345, 'pineapple', 'this is not just apple']
].findIndex(function(a){return a[0] == 1234}); // returns 1

[
  [2439, 'title', 'description'],
  [1234, 'apple', 'this is just apple'],
  [2345, 'pineapple', 'this is not just apple']
].find(function(a){return a[0] == 1234}); // returns [1234, 'apple', 'this is just apple']

I’d recommend to simply use a polyfill as well. See the links: they offer polyfills for both so that Chrome and IE can support this as well.

Upvotes: 0

Related Questions