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

1 Answer 1

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$ Commented May 8, 2015 at 14:37
  • 1
    $\begingroup$ @SuTron I believe now it works as you expect. $\endgroup$ Commented May 8, 2015 at 14:50
  • $\begingroup$ You are a Genius! :) $\endgroup$ Commented May 8, 2015 at 14:53
  • 1
    $\begingroup$ @SuTron glad in help! $\endgroup$ Commented May 8, 2015 at 15:03

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.