@@ -3898,6 +3898,360 @@ export const pythonProblems: Problem[] = [
38983898 validPatterns : [ / S e q u e n c e M a t c h e r \s * \( \s * N o n e \s * , \s * s 1 \s * , \s * s 2 \s * \) \. r a t i o \s * \( \s * \) / ] ,
38993899 tags : [ 'difflib' , 'sequence-matcher' , 'similarity' , 'advanced' ] ,
39003900 } ,
3901+
3902+ // ============================================================
3903+ // DICTIONARY AND DATA MANIPULATION - ADVANCED (25 problems)
3904+ // ============================================================
3905+ {
3906+ id : 'py-dict-020' ,
3907+ category : 'dict' ,
3908+ difficulty : 'easy' ,
3909+ title : 'Counter Basic Usage' ,
3910+ text : 'Count occurrences of each character in the string using Counter' ,
3911+ setup : 'from collections import Counter\ntext = "abracadabra"' ,
3912+ setupCode : 'from collections import Counter\ntext = "abracadabra"' ,
3913+ expected : { a : 5 , b : 2 , r : 2 , c : 1 , d : 1 } ,
3914+ sample : 'dict(Counter(text))' ,
3915+ hints : [ 'Counter counts hashable objects' , 'It returns a Counter object (subclass of dict)' ] ,
3916+ validPatterns : [ / C o u n t e r \s * \( \s * t e x t \s * \) / , / d i c t \s * \( \s * C o u n t e r \s * \( \s * t e x t \s * \) \s * \) / ] ,
3917+ tags : [ 'counter' , 'collections' ] ,
3918+ } ,
3919+ {
3920+ id : 'py-dict-021' ,
3921+ category : 'dict' ,
3922+ difficulty : 'easy' ,
3923+ title : 'Counter Most Common' ,
3924+ text : 'Find the 2 most common elements in the list using Counter' ,
3925+ setup : 'from collections import Counter\nnums = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]' ,
3926+ setupCode : 'from collections import Counter\nnums = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]' ,
3927+ expected : [ [ 4 , 4 ] , [ 3 , 3 ] ] ,
3928+ sample : 'Counter(nums).most_common(2)' ,
3929+ hints : [ 'most_common(n) returns the n most frequent elements' ] ,
3930+ validPatterns : [ / C o u n t e r \s * \( \s * n u m s \s * \) \. m o s t _ c o m m o n \s * \( \s * 2 \s * \) / ] ,
3931+ tags : [ 'counter' , 'collections' ] ,
3932+ } ,
3933+ {
3934+ id : 'py-dict-022' ,
3935+ category : 'dict' ,
3936+ difficulty : 'easy' ,
3937+ title : 'Merge with Pipe Operator' ,
3938+ text : 'Merge base config with override config using | operator' ,
3939+ setup : 'base = {"debug": False, "timeout": 30}\noverride = {"debug": True, "retries": 3}' ,
3940+ setupCode : 'base = {"debug": False, "timeout": 30}\noverride = {"debug": True, "retries": 3}' ,
3941+ expected : { debug : true , timeout : 30 , retries : 3 } ,
3942+ sample : 'base | override' ,
3943+ hints : [ 'Use | to merge dictionaries (Python 3.9+)' ] ,
3944+ validPatterns : [ / b a s e \s * \| \s * o v e r r i d e / ] ,
3945+ tags : [ 'merge' , 'dict-operator' ] ,
3946+ } ,
3947+ {
3948+ id : 'py-dict-023' ,
3949+ category : 'dict' ,
3950+ difficulty : 'easy' ,
3951+ title : 'Dictionary from Two Lists' ,
3952+ text : 'Create a dictionary pairing names with ages' ,
3953+ setup : 'names = ["Alice", "Bob", "Charlie"]\nages = [25, 30, 35]' ,
3954+ setupCode : 'names = ["Alice", "Bob", "Charlie"]\nages = [25, 30, 35]' ,
3955+ expected : { Alice : 25 , Bob : 30 , Charlie : 35 } ,
3956+ sample : 'dict(zip(names, ages))' ,
3957+ hints : [ 'Use zip() to pair corresponding elements' ] ,
3958+ validPatterns : [ / d i c t \s * \( \s * z i p \s * \( \s * n a m e s \s * , \s * a g e s \s * \) \s * \) / ] ,
3959+ tags : [ 'dict-comprehension' , 'zip' ] ,
3960+ } ,
3961+ {
3962+ id : 'py-dict-024' ,
3963+ category : 'dict' ,
3964+ difficulty : 'easy' ,
3965+ title : 'Check Key Existence' ,
3966+ text : 'Check if "email" key exists in the dictionary' ,
3967+ setup : 'user = {"name": "Alice", "age": 30}' ,
3968+ setupCode : 'user = {"name": "Alice", "age": 30}' ,
3969+ expected : false ,
3970+ sample : '"email" in user' ,
3971+ hints : [ 'Use the "in" operator to check key existence' ] ,
3972+ validPatterns : [ / [ " ' ] e m a i l [ " ' ] \s + i n \s + u s e r / ] ,
3973+ tags : [ 'membership' , 'dict-method' ] ,
3974+ } ,
3975+ {
3976+ id : 'py-dict-025' ,
3977+ category : 'dict' ,
3978+ difficulty : 'easy' ,
3979+ title : 'Clear Dictionary' ,
3980+ text : 'Remove all items from the dictionary and return its length' ,
3981+ setup : 'data = {"a": 1, "b": 2, "c": 3}\ndata.clear()' ,
3982+ setupCode : 'data = {"a": 1, "b": 2, "c": 3}\ndata.clear()' ,
3983+ expected : 0 ,
3984+ sample : 'len(data)' ,
3985+ hints : [ 'clear() removes all items in-place' ] ,
3986+ validPatterns : [ / l e n \s * \( \s * d a t a \s * \) / ] ,
3987+ tags : [ 'clear' , 'dict-method' ] ,
3988+ } ,
3989+ {
3990+ id : 'py-dict-026' ,
3991+ category : 'dict' ,
3992+ difficulty : 'easy' ,
3993+ title : 'Enumerate to Index Map' ,
3994+ text : 'Create a dictionary mapping index to fruit using enumerate' ,
3995+ setup : 'fruits = ["apple", "banana", "cherry"]' ,
3996+ setupCode : 'fruits = ["apple", "banana", "cherry"]' ,
3997+ expected : { 0 : 'apple' , 1 : 'banana' , 2 : 'cherry' } ,
3998+ sample : 'dict(enumerate(fruits))' ,
3999+ hints : [ 'enumerate() returns index-value pairs' ] ,
4000+ validPatterns : [ / d i c t \s * \( \s * e n u m e r a t e \s * \( \s * f r u i t s \s * \) \s * \) / ] ,
4001+ tags : [ 'dict-comprehension' , 'enumerate' ] ,
4002+ } ,
4003+ {
4004+ id : 'py-dict-027' ,
4005+ category : 'dict' ,
4006+ difficulty : 'easy' ,
4007+ title : 'Pop with Default' ,
4008+ text : 'Remove and return "status" key with default "unknown" if not found' ,
4009+ setup : 'data = {"name": "test", "value": 42}' ,
4010+ setupCode : 'data = {"name": "test", "value": 42}' ,
4011+ expected : 'unknown' ,
4012+ sample : 'data.pop("status", "unknown")' ,
4013+ hints : [ 'pop() can take a default value as second argument' ] ,
4014+ validPatterns : [ / d a t a \. p o p \s * \( \s * [ " ' ] s t a t u s [ " ' ] \s * , \s * [ " ' ] u n k n o w n [ " ' ] \s * \) / ] ,
4015+ tags : [ 'pop' , 'dict-method' ] ,
4016+ } ,
4017+ {
4018+ id : 'py-dict-028' ,
4019+ category : 'dict' ,
4020+ difficulty : 'medium' ,
4021+ title : 'defaultdict with List' ,
4022+ text : 'Group names by their first letter using defaultdict(list)' ,
4023+ setup : 'from collections import defaultdict\nnames = ["Alice", "Bob", "Anna", "Charlie", "Amy"]\nresult = defaultdict(list)\nfor name in names:\n result[name[0]].append(name)' ,
4024+ setupCode : 'from collections import defaultdict\nnames = ["Alice", "Bob", "Anna", "Charlie", "Amy"]\nresult = defaultdict(list)\nfor name in names:\n result[name[0]].append(name)' ,
4025+ expected : { A : [ 'Alice' , 'Anna' , 'Amy' ] , B : [ 'Bob' ] , C : [ 'Charlie' ] } ,
4026+ sample : 'dict(result)' ,
4027+ hints : [ 'defaultdict(list) auto-creates empty lists' ] ,
4028+ validPatterns : [ / d i c t \s * \( \s * r e s u l t \s * \) / ] ,
4029+ tags : [ 'defaultdict' , 'collections' , 'grouping' ] ,
4030+ } ,
4031+ {
4032+ id : 'py-dict-029' ,
4033+ category : 'dict' ,
4034+ difficulty : 'medium' ,
4035+ title : 'defaultdict with Int' ,
4036+ text : 'Count word occurrences using defaultdict(int)' ,
4037+ setup : 'from collections import defaultdict\nwords = ["a", "b", "a", "c", "b", "a"]\ncounts = defaultdict(int)\nfor w in words:\n counts[w] += 1' ,
4038+ setupCode : 'from collections import defaultdict\nwords = ["a", "b", "a", "c", "b", "a"]\ncounts = defaultdict(int)\nfor w in words:\n counts[w] += 1' ,
4039+ expected : { a : 3 , b : 2 , c : 1 } ,
4040+ sample : 'dict(counts)' ,
4041+ hints : [ 'defaultdict(int) initializes missing keys to 0' ] ,
4042+ validPatterns : [ / d i c t \s * \( \s * c o u n t s \s * \) / ] ,
4043+ tags : [ 'defaultdict' , 'collections' , 'counting' ] ,
4044+ } ,
4045+ {
4046+ id : 'py-dict-030' ,
4047+ category : 'dict' ,
4048+ difficulty : 'medium' ,
4049+ title : 'Nested Dictionary Access' ,
4050+ text : 'Safely get a nested value with get() chaining' ,
4051+ setup : 'data = {"user": {"profile": {"name": "Alice"}}}' ,
4052+ setupCode : 'data = {"user": {"profile": {"name": "Alice"}}}' ,
4053+ expected : 'Alice' ,
4054+ sample : 'data.get("user", {}).get("profile", {}).get("name", "Unknown")' ,
4055+ hints : [ 'Chain get() calls with empty dict defaults' ] ,
4056+ validPatterns : [ / d a t a \. g e t \s * \( .* \) \. g e t \s * \( .* \) \. g e t \s * \( / ] ,
4057+ tags : [ 'nested' , 'safe-access' ] ,
4058+ } ,
4059+ {
4060+ id : 'py-dict-031' ,
4061+ category : 'dict' ,
4062+ difficulty : 'medium' ,
4063+ title : 'Update Nested Dictionary' ,
4064+ text : 'Update the nested name field to "Bob"' ,
4065+ setup : 'data = {"user": {"profile": {"name": "Alice", "age": 30}}}' ,
4066+ setupCode : 'data = {"user": {"profile": {"name": "Alice", "age": 30}}}' ,
4067+ expected : { user : { profile : { name : 'Bob' , age : 30 } } } ,
4068+ sample : 'data["user"]["profile"]["name"] = "Bob"; data' ,
4069+ hints : [ 'Access nested keys with chained brackets' ] ,
4070+ validPatterns : [ / d a t a \s * \[ .* \] \s * \[ .* \] \s * \[ .* \] \s * = \s * [ " ' ] B o b [ " ' ] / ] ,
4071+ tags : [ 'nested' , 'update' ] ,
4072+ } ,
4073+ {
4074+ id : 'py-dict-032' ,
4075+ category : 'dict' ,
4076+ difficulty : 'medium' ,
4077+ title : 'Counter Arithmetic' ,
4078+ text : 'Subtract inventory sold from inventory using Counter subtraction' ,
4079+ setup : 'from collections import Counter\ninventory = Counter({"apple": 10, "banana": 5, "cherry": 3})\nsold = Counter({"apple": 3, "banana": 2})' ,
4080+ setupCode : 'from collections import Counter\ninventory = Counter({"apple": 10, "banana": 5, "cherry": 3})\nsold = Counter({"apple": 3, "banana": 2})' ,
4081+ expected : { apple : 7 , banana : 3 , cherry : 3 } ,
4082+ sample : 'dict(inventory - sold)' ,
4083+ hints : [ 'Counter supports arithmetic operations' ] ,
4084+ validPatterns : [ / i n v e n t o r y \s * - \s * s o l d / ] ,
4085+ tags : [ 'counter' , 'collections' , 'arithmetic' ] ,
4086+ } ,
4087+ {
4088+ id : 'py-dict-033' ,
4089+ category : 'dict' ,
4090+ difficulty : 'medium' ,
4091+ title : 'ChainMap for Config Layers' ,
4092+ text : 'Create a layered config using ChainMap (user overrides defaults)' ,
4093+ setup : 'from collections import ChainMap\ndefaults = {"color": "blue", "size": "medium"}\nuser_prefs = {"color": "red"}' ,
4094+ setupCode : 'from collections import ChainMap\ndefaults = {"color": "blue", "size": "medium"}\nuser_prefs = {"color": "red"}' ,
4095+ expected : { color : 'red' , size : 'medium' } ,
4096+ sample : 'dict(ChainMap(user_prefs, defaults))' ,
4097+ hints : [ 'ChainMap searches maps in order' ] ,
4098+ validPatterns : [ / C h a i n M a p \s * \( \s * u s e r _ p r e f s \s * , \s * d e f a u l t s \s * \) / ] ,
4099+ tags : [ 'chainmap' , 'collections' , 'config' ] ,
4100+ } ,
4101+ {
4102+ id : 'py-dict-034' ,
4103+ category : 'dict' ,
4104+ difficulty : 'medium' ,
4105+ title : 'Dict Comprehension with Conditional Value' ,
4106+ text : 'Create a dict with "pass" or "fail" based on score >= 60' ,
4107+ setup : 'scores = {"Alice": 85, "Bob": 55, "Charlie": 72, "Diana": 45}' ,
4108+ setupCode : 'scores = {"Alice": 85, "Bob": 55, "Charlie": 72, "Diana": 45}' ,
4109+ expected : { Alice : 'pass' , Bob : 'fail' , Charlie : 'pass' , Diana : 'fail' } ,
4110+ sample : '{k: ("pass" if v >= 60 else "fail") for k, v in scores.items()}' ,
4111+ hints : [ 'Use ternary expression in dict comprehension' ] ,
4112+ validPatterns : [ / \{ .* [ " ' ] p a s s [ " ' ] .* i f .* e l s e .* [ " ' ] f a i l [ " ' ] .* f o r .* i n \s + s c o r e s \. i t e m s \s * \( \s * \) \s * \} / ] ,
4113+ tags : [ 'dict-comprehension' , 'conditional' ] ,
4114+ } ,
4115+ {
4116+ id : 'py-dict-035' ,
4117+ category : 'dict' ,
4118+ difficulty : 'medium' ,
4119+ title : 'In-Place Update with |=' ,
4120+ text : 'Update the config dict in-place with new settings using |=' ,
4121+ setup : 'config = {"debug": False, "timeout": 30}\nnew_settings = {"timeout": 60, "retries": 3}' ,
4122+ setupCode : 'config = {"debug": False, "timeout": 30}\nnew_settings = {"timeout": 60, "retries": 3}' ,
4123+ expected : { debug : false , timeout : 60 , retries : 3 } ,
4124+ sample : 'config |= new_settings; config' ,
4125+ hints : [ 'Use |= for in-place dictionary merge (Python 3.9+)' ] ,
4126+ validPatterns : [ / c o n f i g \s * \| = \s * n e w _ s e t t i n g s / ] ,
4127+ tags : [ 'merge' , 'dict-operator' , 'in-place' ] ,
4128+ } ,
4129+ {
4130+ id : 'py-dict-036' ,
4131+ category : 'dict' ,
4132+ difficulty : 'medium' ,
4133+ title : 'Flatten Nested Dict Values' ,
4134+ text : 'Extract all leaf values from nested dict into a flat list' ,
4135+ setup : 'nested = {"a": {"b": 1, "c": 2}, "d": {"e": 3}}' ,
4136+ setupCode : 'nested = {"a": {"b": 1, "c": 2}, "d": {"e": 3}}' ,
4137+ expected : [ 1 , 2 , 3 ] ,
4138+ sample : '[v for inner in nested.values() for v in inner.values()]' ,
4139+ hints : [ 'Use nested comprehension to flatten' ] ,
4140+ validPatterns : [ / \[ .* f o r .* i n \s + n e s t e d \. v a l u e s \s * \( \s * \) \s + f o r .* i n .* \. v a l u e s \s * \( \s * \) \s * \] / ] ,
4141+ tags : [ 'nested' , 'flatten' , 'comprehension' ] ,
4142+ } ,
4143+ {
4144+ id : 'py-dict-037' ,
4145+ category : 'dict' ,
4146+ difficulty : 'medium' ,
4147+ title : 'Counter Total Count' ,
4148+ text : 'Get the total count of all items in the Counter' ,
4149+ setup : 'from collections import Counter\ncounts = Counter({"apple": 5, "banana": 3, "cherry": 2})' ,
4150+ setupCode : 'from collections import Counter\ncounts = Counter({"apple": 5, "banana": 3, "cherry": 2})' ,
4151+ expected : 10 ,
4152+ sample : 'counts.total()' ,
4153+ hints : [ 'Counter has a total() method (Python 3.10+)' ] ,
4154+ validPatterns : [ / c o u n t s \. t o t a l \s * \( \s * \) / , / s u m \s * \( \s * c o u n t s \. v a l u e s \s * \( \s * \) \s * \) / ] ,
4155+ tags : [ 'counter' , 'collections' ] ,
4156+ } ,
4157+ {
4158+ id : 'py-dict-038' ,
4159+ category : 'dict' ,
4160+ difficulty : 'medium' ,
4161+ title : 'Sort Dictionary by Value' ,
4162+ text : 'Sort the dictionary by values in descending order' ,
4163+ setup : 'scores = {"Alice": 85, "Bob": 92, "Charlie": 78, "Diana": 95}' ,
4164+ setupCode : 'scores = {"Alice": 85, "Bob": 92, "Charlie": 78, "Diana": 95}' ,
4165+ expected : { Diana : 95 , Bob : 92 , Alice : 85 , Charlie : 78 } ,
4166+ sample : 'dict(sorted(scores.items(), key=lambda x: x[1], reverse=True))' ,
4167+ hints : [ 'Use sorted() with a key function' ] ,
4168+ validPatterns : [ / d i c t \s * \( \s * s o r t e d \s * \( \s * s c o r e s \. i t e m s \s * \( \s * \) .* r e v e r s e \s * = \s * T r u e / ] ,
4169+ tags : [ 'sorting' , 'dict-method' ] ,
4170+ } ,
4171+ {
4172+ id : 'py-dict-039' ,
4173+ category : 'dict' ,
4174+ difficulty : 'medium' ,
4175+ title : 'OrderedDict Move to End' ,
4176+ text : 'Move the "b" key to the end of the OrderedDict' ,
4177+ setup : 'from collections import OrderedDict\nod = OrderedDict([("a", 1), ("b", 2), ("c", 3)])\nod.move_to_end("b")' ,
4178+ setupCode : 'from collections import OrderedDict\nod = OrderedDict([("a", 1), ("b", 2), ("c", 3)])\nod.move_to_end("b")' ,
4179+ expected : { a : 1 , c : 3 , b : 2 } ,
4180+ sample : 'dict(od)' ,
4181+ hints : [ 'OrderedDict has move_to_end() method' ] ,
4182+ validPatterns : [ / d i c t \s * \( \s * o d \s * \) / ] ,
4183+ tags : [ 'ordereddict' , 'collections' ] ,
4184+ } ,
4185+ {
4186+ id : 'py-dict-040' ,
4187+ category : 'dict' ,
4188+ difficulty : 'hard' ,
4189+ title : 'Deep Merge Dictionaries' ,
4190+ text : 'Merge nested dictionaries recursively (nested values should merge, not replace)' ,
4191+ setup : 'def deep_merge(d1, d2):\n result = d1.copy()\n for k, v in d2.items():\n if k in result and isinstance(result[k], dict) and isinstance(v, dict):\n result[k] = deep_merge(result[k], v)\n else:\n result[k] = v\n return result\nbase = {"a": {"x": 1, "y": 2}, "b": 3}\nupdate = {"a": {"y": 20, "z": 30}, "c": 4}' ,
4192+ setupCode : 'def deep_merge(d1, d2):\n result = d1.copy()\n for k, v in d2.items():\n if k in result and isinstance(result[k], dict) and isinstance(v, dict):\n result[k] = deep_merge(result[k], v)\n else:\n result[k] = v\n return result\nbase = {"a": {"x": 1, "y": 2}, "b": 3}\nupdate = {"a": {"y": 20, "z": 30}, "c": 4}' ,
4193+ expected : { a : { x : 1 , y : 20 , z : 30 } , b : 3 , c : 4 } ,
4194+ sample : 'deep_merge(base, update)' ,
4195+ hints : [ 'Recursively merge when both values are dicts' ] ,
4196+ validPatterns : [ / d e e p _ m e r g e \s * \( \s * b a s e \s * , \s * u p d a t e \s * \) / ] ,
4197+ tags : [ 'nested' , 'merge' , 'recursive' ] ,
4198+ } ,
4199+ {
4200+ id : 'py-dict-041' ,
4201+ category : 'dict' ,
4202+ difficulty : 'hard' ,
4203+ title : 'Group and Aggregate Sales' ,
4204+ text : 'Group sales by product and sum the amounts' ,
4205+ setup : 'from collections import defaultdict\nsales = [{"product": "A", "amount": 100}, {"product": "B", "amount": 200}, {"product": "A", "amount": 150}, {"product": "B", "amount": 50}]\nresult = defaultdict(int)\nfor s in sales:\n result[s["product"]] += s["amount"]' ,
4206+ setupCode : 'from collections import defaultdict\nsales = [{"product": "A", "amount": 100}, {"product": "B", "amount": 200}, {"product": "A", "amount": 150}, {"product": "B", "amount": 50}]\nresult = defaultdict(int)\nfor s in sales:\n result[s["product"]] += s["amount"]' ,
4207+ expected : { A : 250 , B : 250 } ,
4208+ sample : 'dict(result)' ,
4209+ hints : [ 'Use defaultdict(int) for summing' ] ,
4210+ validPatterns : [ / d i c t \s * \( \s * r e s u l t \s * \) / ] ,
4211+ tags : [ 'defaultdict' , 'grouping' , 'aggregation' ] ,
4212+ } ,
4213+ {
4214+ id : 'py-dict-042' ,
4215+ category : 'dict' ,
4216+ difficulty : 'hard' ,
4217+ title : 'Transform JSON-like Data' ,
4218+ text : 'Extract usernames from nested user data into a list' ,
4219+ setup : 'data = {"users": [{"id": 1, "profile": {"username": "alice"}}, {"id": 2, "profile": {"username": "bob"}}, {"id": 3, "profile": {"username": "charlie"}}]}' ,
4220+ setupCode : 'data = {"users": [{"id": 1, "profile": {"username": "alice"}}, {"id": 2, "profile": {"username": "bob"}}, {"id": 3, "profile": {"username": "charlie"}}]}' ,
4221+ expected : [ 'alice' , 'bob' , 'charlie' ] ,
4222+ sample : '[u["profile"]["username"] for u in data["users"]]' ,
4223+ hints : [ 'Access nested structure with bracket notation' ] ,
4224+ validPatterns : [ / \[ .* \[ .* p r o f i l e .* \] .* \[ .* u s e r n a m e .* \] .* f o r .* i n \s + d a t a \s * \[ .* u s e r s .* \] \s * \] / ] ,
4225+ tags : [ 'json' , 'nested' , 'transform' ] ,
4226+ } ,
4227+ {
4228+ id : 'py-dict-043' ,
4229+ category : 'dict' ,
4230+ difficulty : 'hard' ,
4231+ title : 'Counter Elements Expansion' ,
4232+ text : 'Expand Counter back to list of individual elements' ,
4233+ setup : 'from collections import Counter\ncounts = Counter({"a": 3, "b": 2, "c": 1})' ,
4234+ setupCode : 'from collections import Counter\ncounts = Counter({"a": 3, "b": 2, "c": 1})' ,
4235+ expected : [ 'a' , 'a' , 'a' , 'b' , 'b' , 'c' ] ,
4236+ sample : 'list(counts.elements())' ,
4237+ hints : [ 'Counter has an elements() method' ] ,
4238+ validPatterns : [ / l i s t \s * \( \s * c o u n t s \. e l e m e n t s \s * \( \s * \) \s * \) / ] ,
4239+ tags : [ 'counter' , 'collections' , 'expansion' ] ,
4240+ } ,
4241+ {
4242+ id : 'py-dict-044' ,
4243+ category : 'dict' ,
4244+ difficulty : 'hard' ,
4245+ title : 'Pivot Data Structure' ,
4246+ text : 'Pivot list of dicts to dict of lists by key' ,
4247+ setup : 'records = [{"name": "Alice", "score": 85}, {"name": "Bob", "score": 90}, {"name": "Charlie", "score": 78}]' ,
4248+ setupCode : 'records = [{"name": "Alice", "score": 85}, {"name": "Bob", "score": 90}, {"name": "Charlie", "score": 78}]' ,
4249+ expected : { name : [ 'Alice' , 'Bob' , 'Charlie' ] , score : [ 85 , 90 , 78 ] } ,
4250+ sample : '{k: [r[k] for r in records] for k in records[0].keys()}' ,
4251+ hints : [ 'Get keys from first record' ] ,
4252+ validPatterns : [ / \{ .* : \s * \[ .* f o r .* i n \s + r e c o r d s \s * \] .* f o r .* i n \s + r e c o r d s \s * \[ \s * 0 \s * \] / ] ,
4253+ tags : [ 'pivot' , 'transform' , 'comprehension' ] ,
4254+ } ,
39014255] ;
39024256
39034257export default pythonProblems ;
0 commit comments