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:
-
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. -
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 usingString()
before being used as a key. -
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]
andvaluesArr = ['a', 'b', 'c']
, the result would be{'1': 'a', '2': 'b'}
. The second occurrence of key1
(at index 2) is ignored. - If
keysArr = ['x', 5, 'x']
andvaluesArr = [10, 20, 30]
, the result would be{'x': 10, '5': 20}
. The number5
is converted to string'5'
, and the duplicate'x'
at index 2 is ignored.
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
, orfalse
), the key already exists, so we skip it
This approach works because:
- We process keys in order from index 0 to the end, ensuring the first occurrence is always processed first
- Once a key is added to the object, any subsequent occurrence will fail the
undefined
check and be skipped - 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:
-
Initialize an empty object: Create
ans
as an empty Record/object that will store our final key-value pairs.const ans: Record<string, any> = {};
-
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)
-
Convert key to string: For each iteration, get the key at index
i
and convert it to a string usingString()
. This ensures all keys are strings regardless of their original type.const k = String(keysArr[i]);
-
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]; }
- If
-
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 toundefined
- we only set actual values fromvaluesArr[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 evennull
orundefined
keys
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample 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:
-
Initialize: Create empty object
ans = {}
-
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}
- Key:
-
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"}
- Key:
-
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)
- Key:
-
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"}
- Key:
-
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)
- Key:
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)
wherem
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 mostn
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 invaluesArr
) - 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
Which of the tree traversal order can be used to obtain elements in a binary search tree in sorted order?
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!