Facebook Pixel

2794. Create Object from Two Arrays 🔒

Problem Description

You need to create an object from two arrays - one containing keys and another containing values. The arrays keysArr and valuesArr should be combined such that each key at index i in keysArr is paired with the corresponding value at index i in valuesArr.

The problem has three main requirements:

  1. Handle duplicate keys: If the same key appears multiple times in keysArr, only use its first occurrence. Any subsequent appearances of that key should be ignored, meaning the key-value pair at later indices won't be added to the resulting object.

  2. Convert non-string keys: All keys must be strings in the final object. If a key in keysArr is not already a string (like a number, boolean, or other type), it should be converted to a string using String() before being used as a key.

  3. Return format: The function should return a Record/Object where each property represents a key-value pair from the input arrays.

For example:

  • If keysArr = [1, 2, 1] and valuesArr = ['a', 'b', 'c'], the result would be {'1': 'a', '2': 'b'}. The second occurrence of key 1 (at index 2) is ignored.
  • If keysArr = ['x', 5, 'x'] and valuesArr = [10, 20, 30], the result would be {'x': 10, '5': 20}. The number 5 is converted to string '5', and the duplicate 'x' at index 2 is ignored.
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is that we need to build an object while maintaining the "first occurrence wins" rule for duplicate keys. This naturally suggests iterating through the arrays once from start to end, checking if each key has already been added before inserting it.

To handle this efficiently, we can leverage JavaScript/TypeScript's object property checking. When we encounter a key, we first convert it to a string using String() to ensure consistency. Then, before adding a key-value pair, we check if ans[k] === undefined. This condition tells us whether the key has been used before:

  • If the value is undefined, the key hasn't been added yet, so we can safely add it
  • If the value is anything else (including null, 0, or false), the key already exists, so we skip it

This approach works because:

  1. We process keys in order from index 0 to the end, ensuring the first occurrence is always processed first
  2. Once a key is added to the object, any subsequent occurrence will fail the undefined check and be skipped
  3. The String() conversion handles all data types uniformly - numbers become their string representation, booleans become "true" or "false", and strings remain unchanged

The time complexity is O(n) where n is the length of the arrays, as we only need one pass through the data. The space complexity is also O(n) for storing the resulting object.

Solution Approach

The solution uses a straightforward iteration approach with a hash map (object) to track and store key-value pairs.

Step-by-step implementation:

  1. Initialize an empty object: Create ans as an empty Record/object that will store our final key-value pairs.

    const ans: Record<string, any> = {};
  2. Iterate through the arrays: Use a for loop to traverse both arrays simultaneously using the same index i.

    for (let i = 0; i < keysArr.length; ++i)
  3. Convert key to string: For each iteration, get the key at index i and convert it to a string using String(). This ensures all keys are strings regardless of their original type.

    const k = String(keysArr[i]);
  4. Check for duplicate keys: Before adding the key-value pair, check if the key already exists in our object by testing if ans[k] === undefined.

    • If undefined: This is the first occurrence of this key, so we add it
    • If not undefined: The key already exists (from an earlier index), so we skip it
    if (ans[k] === undefined) {
        ans[k] = valuesArr[i];
    }
  5. Return the result: After processing all elements, return the constructed object.

Why this approach works:

  • The undefined check is reliable because we never explicitly set a value to undefined - we only set actual values from valuesArr[i]
  • Processing from index 0 upward ensures the first occurrence is always the one that gets stored
  • The String() conversion handles edge cases like numeric keys (1 becomes "1"), boolean keys (true becomes "true"), and even null or undefined keys

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a concrete example to see how the solution handles duplicate keys and type conversion.

Example Input:

  • keysArr = [1, "name", 1, true, "name"]
  • valuesArr = [100, "Alice", 200, "yes", "Bob"]

Step-by-step execution:

  1. Initialize: Create empty object ans = {}

  2. Iteration 1 (i=0):

    • Key: 1 (number) → Convert to string: "1"
    • Check: ans["1"] === undefined? YES
    • Action: Add ans["1"] = 100
    • Result: ans = {"1": 100}
  3. Iteration 2 (i=1):

    • Key: "name" (already string) → Remains: "name"
    • Check: ans["name"] === undefined? YES
    • Action: Add ans["name"] = "Alice"
    • Result: ans = {"1": 100, "name": "Alice"}
  4. Iteration 3 (i=2):

    • Key: 1 (number) → Convert to string: "1"
    • Check: ans["1"] === undefined? NO (value is 100)
    • Action: Skip (duplicate key)
    • Result: ans = {"1": 100, "name": "Alice"} (unchanged)
  5. Iteration 4 (i=3):

    • Key: true (boolean) → Convert to string: "true"
    • Check: ans["true"] === undefined? YES
    • Action: Add ans["true"] = "yes"
    • Result: ans = {"1": 100, "name": "Alice", "true": "yes"}
  6. Iteration 5 (i=4):

    • Key: "name" (string) → Remains: "name"
    • Check: ans["name"] === undefined? NO (value is "Alice")
    • Action: Skip (duplicate key)
    • Result: ans = {"1": 100, "name": "Alice", "true": "yes"} (unchanged)

Final Output: {"1": 100, "name": "Alice", "true": "yes"}

Notice how:

  • The duplicate key 1 at index 2 was ignored, keeping the first value (100) instead of 200
  • The duplicate key "name" at index 4 was ignored, keeping "Alice" instead of "Bob"
  • The number 1 was converted to string "1"
  • The boolean true was converted to string "true"

Solution Implementation

1def createObject(keysArr, valuesArr):
2    """
3    Creates a dictionary from two arrays - one containing keys and one containing values.
4    If duplicate keys exist, only the first occurrence is used.
5  
6    Args:
7        keysArr: List of keys to be used as dictionary keys
8        valuesArr: List of values corresponding to the keys
9  
10    Returns:
11        A dictionary mapping keys to values
12    """
13    # Initialize an empty dictionary to store the key-value pairs
14    result = {}
15  
16    # Iterate through the keys array
17    for i in range(len(keysArr)):
18        # Convert the current key to string format
19        key = str(keysArr[i])
20      
21        # Only assign value if the key hasn't been set before (handles duplicates)
22        if key not in result:
23            result[key] = valuesArr[i]
24  
25    return result
26
1import java.util.HashMap;
2import java.util.Map;
3
4/**
5 * Creates a map from two arrays - one containing keys and one containing values.
6 * If duplicate keys exist, only the first occurrence is used.
7 * 
8 * @param keysArr - Array of keys to be used as map keys
9 * @param valuesArr - Array of values corresponding to the keys
10 * @return A map mapping keys to values
11 */
12public static Map<String, Object> createObject(Object[] keysArr, Object[] valuesArr) {
13    // Initialize an empty HashMap to store the key-value pairs
14    Map<String, Object> result = new HashMap<>();
15  
16    // Iterate through the keys array
17    for (int i = 0; i < keysArr.length; i++) {
18        // Convert the current key to String format
19        String key = String.valueOf(keysArr[i]);
20      
21        // Only put value if the key hasn't been set before (handles duplicates)
22        // containsKey check ensures we keep the first occurrence
23        if (!result.containsKey(key)) {
24            // Check if values array has a corresponding element at this index
25            if (i < valuesArr.length) {
26                result.put(key, valuesArr[i]);
27            } else {
28                // If no corresponding value exists, map to null
29                result.put(key, null);
30            }
31        }
32    }
33  
34    return result;
35}
36
1#include <unordered_map>
2#include <vector>
3#include <string>
4#include <any>
5
6/**
7 * Creates an object from two arrays - one containing keys and one containing values.
8 * If duplicate keys exist, only the first occurrence is used.
9 * 
10 * @param keysArr - Array of keys to be used as object properties
11 * @param valuesArr - Array of values corresponding to the keys
12 * @returns An unordered_map mapping keys to values
13 */
14std::unordered_map<std::string, std::any> createObject(
15    const std::vector<std::any>& keysArr, 
16    const std::vector<std::any>& valuesArr) {
17  
18    // Initialize an empty unordered_map to store the key-value pairs
19    std::unordered_map<std::string, std::any> result;
20  
21    // Iterate through the keys array
22    for (size_t i = 0; i < keysArr.size(); ++i) {
23        // Convert the current key to string format
24        // Using std::any_cast to convert to string
25        std::string key;
26        try {
27            // Try to cast the any type to various possible types and convert to string
28            if (keysArr[i].type() == typeid(std::string)) {
29                key = std::any_cast<std::string>(keysArr[i]);
30            } else if (keysArr[i].type() == typeid(int)) {
31                key = std::to_string(std::any_cast<int>(keysArr[i]));
32            } else if (keysArr[i].type() == typeid(double)) {
33                key = std::to_string(std::any_cast<double>(keysArr[i]));
34            } else if (keysArr[i].type() == typeid(const char*)) {
35                key = std::string(std::any_cast<const char*>(keysArr[i]));
36            } else {
37                // For other types, skip this iteration
38                continue;
39            }
40        } catch (const std::bad_any_cast& e) {
41            // If casting fails, skip this iteration
42            continue;
43        }
44      
45        // Only assign value if the key hasn't been set before (handles duplicates)
46        // find() returns end() if key doesn't exist
47        if (result.find(key) == result.end()) {
48            // Check if index is within bounds of valuesArr
49            if (i < valuesArr.size()) {
50                result[key] = valuesArr[i];
51            } else {
52                // If valuesArr is shorter, assign empty std::any
53                result[key] = std::any{};
54            }
55        }
56    }
57  
58    return result;
59}
60
1/**
2 * Creates an object from two arrays - one containing keys and one containing values.
3 * If duplicate keys exist, only the first occurrence is used.
4 * 
5 * @param keysArr - Array of keys to be used as object properties
6 * @param valuesArr - Array of values corresponding to the keys
7 * @returns An object mapping keys to values
8 */
9function createObject(keysArr: any[], valuesArr: any[]): Record<string, any> {
10    // Initialize an empty object to store the key-value pairs
11    const result: Record<string, any> = {};
12  
13    // Iterate through the keys array
14    for (let i = 0; i < keysArr.length; ++i) {
15        // Convert the current key to string format
16        const key: string = String(keysArr[i]);
17      
18        // Only assign value if the key hasn't been set before (handles duplicates)
19        if (result[key] === undefined) {
20            result[key] = valuesArr[i];
21        }
22    }
23  
24    return result;
25}
26

Time and Space Complexity

Time Complexity: O(n * m) where n is the length of the keysArr and m is the average length of the string representation of keys.

  • The function iterates through the keysArr once with a for loop: O(n)
  • Inside each iteration:
    • String(keysArr[i]) conversion: O(m) where m is the length of the string representation
    • Checking if ans[k] === undefined: O(1) average case for object property access
    • Assignment ans[k] = valuesArr[i]: O(1) average case
  • Total: O(n * m)

If we consider the string conversion as O(1) for primitive types (which is often the case for numbers and short strings), the time complexity simplifies to O(n).

Space Complexity: O(n * (m + v)) where n is the number of unique keys, m is the average length of string keys, and v is the average space for stored values.

  • The ans object stores at most n key-value pairs
  • Each key takes O(m) space after string conversion
  • Each value takes O(v) space (depending on the type and size of values in valuesArr)
  • Total: O(n * (m + v))

For practical purposes with primitive values and reasonable key lengths, this can be simplified to O(n).

Common Pitfalls

1. Mishandling Special Values in Arrays

One critical pitfall occurs when the valuesArr contains special values like None, False, or 0. If you were to check for existing keys using a condition like if not result.get(key): instead of if key not in result:, you would incorrectly skip keys that have falsy values.

Problem Example:

# Incorrect approach
def createObject_wrong(keysArr, valuesArr):
    result = {}
    for i in range(len(keysArr)):
        key = str(keysArr[i])
        # WRONG: This fails when the value is falsy
        if not result.get(key):  
            result[key] = valuesArr[i]
    return result

# Test case that breaks
keysArr = ['a', 'b', 'a']
valuesArr = [0, 1, 2]
# Expected: {'a': 0, 'b': 1}
# Actual with wrong approach: {'a': 2, 'b': 1}  # 'a' gets overwritten!

Solution: Always use if key not in result: to check for key existence, not value truthiness.

2. Assuming Equal Array Lengths

The current implementation assumes both arrays have the same length and uses len(keysArr) for iteration. If valuesArr is shorter, this causes an IndexError.

Problem Example:

keysArr = ['a', 'b', 'c']
valuesArr = ['x', 'y']  # Shorter array
# This would raise: IndexError: list index out of range

Solution: Use the minimum length of both arrays:

def createObject_safe(keysArr, valuesArr):
    result = {}
    # Use minimum length to avoid index errors
    for i in range(min(len(keysArr), len(valuesArr))):
        key = str(keysArr[i])
        if key not in result:
            result[key] = valuesArr[i]
    return result

3. String Conversion Edge Cases

While str() handles most types well, be aware that custom objects or complex data structures as keys might produce unexpected string representations.

Problem Example:

class CustomObj:
    def __init__(self, val):
        self.val = val
    # No __str__ method defined

obj1 = CustomObj(1)
obj2 = CustomObj(2)
keysArr = [obj1, obj2, obj1]
valuesArr = ['a', 'b', 'c']
# Result keys will be like '<__main__.CustomObj object at 0x...>'
# And obj1 and obj2 might have different memory addresses!

Solution: Document that the function expects primitive types or objects with well-defined string representations, or add validation:

def createObject_validated(keysArr, valuesArr):
    result = {}
    for i in range(min(len(keysArr), len(valuesArr))):
        # Optionally validate key types
        if not isinstance(keysArr[i], (str, int, float, bool, type(None))):
            raise ValueError(f"Unsupported key type: {type(keysArr[i])}")
        key = str(keysArr[i])
        if key not in result:
            result[key] = valuesArr[i]
    return result
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which of the tree traversal order can be used to obtain elements in a binary search tree in sorted order?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More