skip to Main Content

I have an array of similar objects like this:

const urls = [
    {
        title: "title 1",
        url: "https://example.com/1" 
    },
    {
        title: "title 2",
        url: "https://example.com/2" 
    },
    ...
] 

To reduce the repetition, I think of making a class:

class URL {
    title: string
    url: string
   
    constructor(title:string, url:string) {
        this.title = title
        this.url = url
    } 
} 

const link1 = new URL("title 1", "https://example.com/1")
const link2 = new URL("title 2", "https://example.com/2")

This has 2 cons:

  • I have to assign unused variable names
  • Create an array of them seem to lead to memory leak

Is there a better way? My goal is to run a filter on the array (input a specific title, output its corresponding url).

2

Answers


  1. From what you describe what you actually want is just a lookup using a title to obtain a URL.

    You should not be using arrays for this at all (at least for a larger amount of URLs). Best to use a Map or a JS object since those are designed for lookups and can therefore do them very fast i. e. sub-linear.

    From the MDN docs:

    The specification requires maps to be implemented "that, on average, provide access times that are sublinear on the number of elements in the collection". Therefore, it could be represented internally as a hash table (with O(1) lookup), a search tree (with O(log(N)) lookup), or any other data structure, as long as the complexity is better than O(N).

    With JavaScript object

    const urls = {
      "title 1": "https://example.com/1",
      "title 2": "https://example.com/2",
    };
    console.log(urls["title 1"]);
    console.log(urls["Non-existing title"] ?? "No URL found for this title");

    With a Map

    const urlMap = new Map();
    urlMap.set("title 1", "https://example.com/1");
    urlMap.set("title 2", "https://example.com/2");
    
    console.log(urlMap.get("title 1"));
    console.log(urlMap.get("Non-existing title") ?? "No URL found for this title");

    Lookup URL by titles following a specific pattern

    If your titles follow a specific pattern and you want to be smart about things and not waste storage unnecessarily you could also do something like the following:

    • parse title to obtain a lookup key and other information encoded in the title
    • use title to lookup the base URL
    • use other information encoded in the title to adjust the URL (path params, search params etc.)

    Here a very simple example based on your example. Depending on the complexity of your title and your URLs this can get much more complex.

    const urls = {
      title: new URL("https://example.com"),
      anothertitle: new URL("https://anothertitle.net")
    };
    
    /**
     * Gets a URL with parameter for a title with a specific format.
     * @param {string} title title
     * @returns {URL} Url
     */
    function getUrlForTitle(title) {
      const [key, pathValue] = title.split(" "); // you could of course use some Regex here and throw an error if it doesn't match
      const url = urls[key];
      if (url === undefined) throw new Error(`No URL found for title '${title}'`);
      url.pathname = `/${pathValue}`;
      return url;
    }
    
    console.log(getUrlForTitle("title 1").toString());
    console.log(getUrlForTitle("title 2").toString());
    console.log(getUrlForTitle("title 12").toString());
    console.log(getUrlForTitle("anothertitle 145").toString());
    // errors
    console.log(getUrlForTitle("unknowntitle 145").toString());
    /* Stackoverflow: show only console */
    .as-console-wrapper {
      max-height: 100% !important;
      top: 0;
    }
    Login or Signup to reply.
  2. If your goal is to filter the array based on the title and retrieve the corresponding URL, you can achieve it without creating instances of a class. You can use an object or a Map to store the titles as keys and their corresponding URLs as values. Here’s how you can do it:

    const urls = [
        {
            title: "title 1",
            url: "https://example.com/1" 
        },
        {
            title: "title 2",
            url: "https://example.com/2" 
        },   
    ];
    
    const urlsMap = new Map(urls.map(item => [item.title, item.url]));
    
    const getUrlByTitle = (title) => {
        return urlsMap.get(title) || null; 
    };
    
    const titleToSearch = "title 1";
    const url = getUrlByTitle(titleToSearch);
    if (url) {
        console.log(`URL for ${titleToSearch}: ${url}`);
    } else {
        console.log(`No URL found for ${titleToSearch}`);
    }
    
    

    In this approach:

    • You define the URLs as key-value pairs in an object (urls).
    • The getUrlByTitle function takes a title as input and returns the corresponding URL from the urls object.
    • If the title is found in the urls object, it returns the corresponding URL; otherwise, it returns null.

    This approach eliminates the need to create instances of a class and avoids memory overhead. It also simplifies the code and makes it more concise.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search