4
$\begingroup$

Considering we have a list of rules:

lst = {"A" -> {"A1" -> {"a.124" -> "45", "a.125" -> "45"}, 
    "A2" -> "something", 
    "B" -> {"b[1].sqw" -> "true", "b[1].ewq" -> "false", 
      "b[2].tyy" -> "saved", "b[2].bfg" -> "iid:"}, "C" -> "eb9d"}}

Note*: I know that the delimiter is always a point - .

How can I "combine" the keys and make another list of vales having as a result:

res = {"A" -> {"A1" -> {"a" -> {"124" -> "45", 
        "125" -> "45"}}, "A2" -> "something", 
    "B" -> {"b[1]" -> {"sqw" -> "true", "ewq" -> "false"}, 
      "b[2]" -> {"tyy" -> "saved", "bfg" -> "iid:"}}, "C" -> "eb9d"}}

UPDATE

A real data example:

{"crs" -> {"BlueHue" -> "0", "BlueSaturation" -> "0", 
   "CameraProfile" -> "Adobe Standard", "ColorNoiseReduction" -> "25",
    "ColorNoiseReductionDetail" -> "50", "Contrast2012" -> "0", 
   "DefringeGreenHueHi" -> "60", "DefringeGreenHueLo" -> "40", 
   "Exposure2012" -> "+0.45", "GreenHue" -> "0", 
   "GreenSaturation" -> "0", "HasCrop" -> "False", 
   "HasSettings" -> "True", "LuminanceSmoothing" -> "0", 
   "ParametricShadowSplit" -> "25", "ParametricShadows" -> "0", 
   "PostCropVignetteAmount" -> "0", "RedHue" -> "0", 
   "RedSaturation" -> "0", "Saturation" -> "0", 
   "SaturationAdjustmentAqua" -> "0", 
   "SaturationAdjustmentBlue" -> "0", 
   "SaturationAdjustmentGreen" -> "0", 
   "SaturationAdjustmentMagenta" -> "0", 
   "SaturationAdjustmentOrange" -> "0", 
   "SaturationAdjustmentPurple" -> "0", 
   "SaturationAdjustmentRed" -> "0", 
   "SaturationAdjustmentYellow" -> "0", "ShadowTint" -> "0", 
   "Shadows2012" -> "+25", "Sharpness" -> "103", 
   "SplitToningHighlightSaturation" -> "0", 
   "SplitToningShadowSaturation" -> "0", "Temperature" -> "3700", 
   "Tint" -> "+16", "ToneCurveName2012" -> "Medium Contrast", 
   "ToneCurvePV2012" -> 
    "0, 0, 32, 22, 64, 56, 128, 128, 192, 196, 255, 255", 
   "ToneCurvePV2012Blue" -> "0, 0, 255, 255", 
   "ToneCurvePV2012Green" -> "0, 0, 255, 255", 
   "ToneCurvePV2012Red" -> "0, 0, 255, 255", "VignetteAmount" -> "0", 
   "WhiteBalance" -> "As Shot"}, 
 "dc" -> {"creator" -> "unknown", "format" -> "image/jpeg"}, 
 "photoshop" -> {"DateCreated" -> "2014-04-28T14:52:32"}, 
 "xmp" -> {"CreateDate" -> "2014-04-28T14:52:32", 
   "CreatorTool" -> "Adobe Photoshop Lightroom 5.0 (Macintosh)", 
   "MetadataDate" -> "2014-04-28T16:11:27-05:00", 
   "ModifyDate" -> "2014-04-28T16:11:27-05:00", "Rating" -> "5"}, 
 "xmpMM" -> {"DerivedFrom" -> {"DerivedFrom.documentID" -> 
      "45DA984AC12B4C2E29FD2841B1732B26", 
     "DerivedFrom.originalDocumentID" -> 
      "45DA984AC12B4C2E29FD2841B1732B26"}, 
   "DocumentID" -> "xmp.did:8669ed4e-bda9-48dd-80cd-4fd3aeef1e06", 
   "History" -> {"History[1].action" -> "derived", 
     "History[1].parameters" -> 
      "converted from image/x-canon-cr2 to image/jpeg, saved to new \
location", "History[2].action" -> "saved", 
     "History[2].instanceID" -> 
      "xmp.iid:8669ed4e-bda9-48dd-80cd-4fd3aeef1e06", 
     "History[2].when" -> "2014-04-28T16:00:23-05:00", 
     "History[2].softwareAgent" -> 
      "Adobe Photoshop Lightroom 5.0 (Macintosh)", 
     "History[2].changed" -> "/", "History[3].action" -> "saved", 
     "History[3].instanceID" -> 
      "xmp.iid:6c92b810-3d29-4c6c-8565-a7f150f0eb9d", 
     "History[3].when" -> "2014-04-28T16:11:27-05:00", 
     "History[3].softwareAgent" -> "Adobe Photoshop CC (Macintosh)", 
     "History[3].changed" -> "/"}, 
   "InstanceID" -> "xmp.iid:6c92b810-3d29-4c6c-8565-a7f150f0eb9d", 
   "OriginalDocumentID" -> "45DA984AC12B4C2E29FD2841B1732B26"}}
$\endgroup$
0
3
$\begingroup$

Here is one way:

splitAndGroup[list_List]:=Module[{splitedList},
    splitedList=MapAt[StringSplit[#,"."]&,list,{All,1}];
    Normal@GroupBy[splitedList,(#[[1,1]]&),MapAt[Last,{All,1}]]
]

convert[list_List]:=Map[splitAndGroup,lst,{-3}]

Now using:

lst = {
   "A" -> {"A1" -> {"a.124" -> "45", "a.125" -> "45"}, 
   "A2" -> "something", 
   "B" -> {"b[1].sqw" -> "true", "b[1].ewq" -> "false", 
      "b[2].tyy" -> "saved", "b[2].bfg" -> "iid:"},
   "C" -> "eb9d"}
}

You can do convert@lst to get:

   {
     "A"->{"A1"->{"a"->{124->45,125->45}},
     "A2"->"something",
     "B"->{"b[1]"->{"sqw"->"true","ewq"->"false"},
           "b[2]"->{"tyy"->"saved","bfg"->"iid:"}}
    ,"C"->"eb9d"}
   }

And if you need it in Association form:

Needs["GeneralUtilities`"]
ToAssociations@convert@lst

 <|
  "A"-><|"A1"-><|"a"-><|"124"->"45","125"->"45"|>|>,
  "A2"->"something",
  "B"-><|"b[1]"-><|"sqw"->"true","ewq"->"false"|>,
         "b[2]"-><|"tyy"->"saved","bfg"->"iid:"|>|>,
  "C"->"eb9d"|>
 |>

Update

For the real case, there are lists that should not be splited. Like this one:

"dc" -> {"creator" -> "unknown", "format" -> "image/jpeg"}

Just add a If in splitAndGroup, like this:

splitAndGroup[list_List]:=Module[{splitedList},
    splitedList=MapAt[StringSplit[#,"."]&,list,{All,1}];
    If[Length@splitedList[[1,1]]==1,Return@list];
    Normal@GroupBy[splitedList,(#[[1,1]]&),MapAt[Last,{All,1}]]
]
$\endgroup$
4
  • $\begingroup$ Thanks for the great answer! I have posted an update with a real data that I use. Your function gives a strange result for that data. Could you please comment? Thanks! $\endgroup$
    – SuTron
    May 8 '15 at 14:37
  • 1
    $\begingroup$ @SuTron I believe now it works as you expect. $\endgroup$
    – Murta
    May 8 '15 at 14:50
  • $\begingroup$ You are a Genius! :) $\endgroup$
    – SuTron
    May 8 '15 at 14:53
  • 1
    $\begingroup$ @SuTron glad in help! $\endgroup$
    – Murta
    May 8 '15 at 15:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.