Index: /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/MenuItems/ShrinkDataAnalysisRunsMenuItem.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/MenuItems/ShrinkDataAnalysisRunsMenuItem.cs	(revision 15475)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Views/3.4/MenuItems/ShrinkDataAnalysisRunsMenuItem.cs	(revision 15476)
@@ -23,9 +23,6 @@
 
 using System;
-using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
-using System.Linq.Expressions;
-using HeuristicLab.Common;
 using HeuristicLab.MainForm;
 using HeuristicLab.Optimization;
@@ -33,5 +30,4 @@
 
 using MenuItem = HeuristicLab.MainForm.WindowsForms.MenuItem;
-using ValuesType = System.Collections.Generic.Dictionary<string, System.Collections.IList>;
 
 namespace HeuristicLab.Problems.DataAnalysis.Views {
@@ -79,61 +75,11 @@
       mainForm.AddOperationProgressToContent(activeView.Content, "Removing duplicate datasets.");
 
-      Action<IContentView> action = (view) => {
-        var variableValuesMapping = new Dictionary<ValuesType, ValuesType>();
-        foreach (var problemData in view.Content.GetObjectGraphObjects(excludeStaticMembers: true).OfType<IDataAnalysisProblemData>()) {
-          var dataset = problemData.Dataset as Dataset;
-          if (dataset == null) continue;
-          var originalValues = variableValuesGetter(dataset);
-          var matchingValues = GetEqualValues(originalValues, variableValuesMapping);
-          variableValuesSetter(dataset, matchingValues);
-        }
-      };
+      Action<IContentView> action = (view) => DatasetUtil.RemoveDuplicateDatasets(view.Content);
 
-      action.BeginInvoke(activeView, delegate(IAsyncResult result) {
+      action.BeginInvoke(activeView, delegate (IAsyncResult result) {
         action.EndInvoke(result);
         mainForm.RemoveOperationProgressFromContent(activeView.Content);
       }, null);
     }
-
-    private static ValuesType GetEqualValues(ValuesType originalValues, Dictionary<ValuesType, ValuesType> variableValuesMapping) {
-      if (variableValuesMapping.ContainsKey(originalValues)) return variableValuesMapping[originalValues];
-
-      var matchingValues = variableValuesMapping.FirstOrDefault(kv => kv.Key == kv.Value && EqualVariableValues(originalValues, kv.Key)).Key ?? originalValues;
-      variableValuesMapping[originalValues] = matchingValues;
-      return matchingValues;
-    }
-
-    private static bool EqualVariableValues(ValuesType values1, ValuesType values2) {
-      //compare variable names for equality
-      if (!values1.Keys.SequenceEqual(values2.Keys)) return false;
-      foreach (var key in values1.Keys) {
-        var v1 = values1[key];
-        var v2 = values2[key];
-        if (v1.Count != v2.Count) return false;
-        for (int i = 0; i < v1.Count; i++) {
-          if (!v1[i].Equals(v2[i])) return false;
-        }
-      }
-      return true;
-    }
-
-    private static readonly Action<Dataset, Dictionary<string, IList>> variableValuesSetter;
-    private static readonly Func<Dataset, Dictionary<string, IList>> variableValuesGetter;
-    /// <summary>
-    /// The static initializer is used to create expressions for getting and setting the private variableValues field in the dataset.
-    /// This is done by expressions because the field is private and compiled expression calls are much faster compared to standad reflection calls.
-    /// </summary>
-    static ShrinkDataAnalysisRunsMenuItem() {
-      var dataset = Expression.Parameter(typeof(Dataset));
-      var variableValues = Expression.Parameter(typeof(ValuesType));
-      var valuesExpression = Expression.Field(dataset, "variableValues");
-      var assignExpression = Expression.Assign(valuesExpression, variableValues);
-
-      var variableValuesSetExpression = Expression.Lambda<Action<Dataset, ValuesType>>(assignExpression, dataset, variableValues);
-      variableValuesSetter = variableValuesSetExpression.Compile();
-
-      var variableValuesGetExpression = Expression.Lambda<Func<Dataset, ValuesType>>(valuesExpression, dataset);
-      variableValuesGetter = variableValuesGetExpression.Compile();
-    }
   }
 }
Index: /stable/HeuristicLab.Problems.DataAnalysis/3.4/DatasetUtil.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis/3.4/DatasetUtil.cs	(revision 15475)
+++ /stable/HeuristicLab.Problems.DataAnalysis/3.4/DatasetUtil.cs	(revision 15476)
@@ -23,11 +23,13 @@
 using System.Collections;
 using System.Collections.Generic;
-using System.ComponentModel;
 using System.Linq;
-using System.Text;
+using System.Linq.Expressions;
+using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Random;
 
 namespace HeuristicLab.Problems.DataAnalysis {
+  using ValuesType = Dictionary<string, IList>;
+
   public static class DatasetUtil {
     /// <summary>
@@ -57,5 +59,65 @@
       }
       return shuffled;
+    }
 
+    private static readonly Action<Dataset, ValuesType> setValues;
+    private static readonly Func<Dataset, ValuesType> getValues;
+    static DatasetUtil() {
+      var dataset = Expression.Parameter(typeof(Dataset));
+      var variableValues = Expression.Parameter(typeof(ValuesType));
+      var valuesExpression = Expression.Field(dataset, "variableValues");
+      var assignExpression = Expression.Assign(valuesExpression, variableValues);
+
+      var variableValuesSetExpression = Expression.Lambda<Action<Dataset, ValuesType>>(assignExpression, dataset, variableValues);
+      setValues = variableValuesSetExpression.Compile();
+
+      var variableValuesGetExpression = Expression.Lambda<Func<Dataset, ValuesType>>(valuesExpression, dataset);
+      getValues = variableValuesGetExpression.Compile();
+    }
+
+    public static void RemoveDuplicateDatasets(IContent content) {
+      var variableValuesMapping = new Dictionary<ValuesType, ValuesType>();
+
+      foreach (var problemData in content.GetObjectGraphObjects(excludeStaticMembers: true).OfType<IDataAnalysisProblemData>()) {
+        var dataset = problemData.Dataset as Dataset;
+        if (dataset == null) continue;
+
+        var originalValues = getValues(dataset);
+
+        ValuesType matchingValues;
+
+        variableValuesMapping.GetEqualValues(originalValues, out matchingValues);
+
+        setValues(dataset, matchingValues);
+      }
+    }
+
+    private static bool GetEqualValues(this Dictionary<ValuesType, ValuesType> variableValuesMapping, ValuesType originalValues, out ValuesType matchingValues) {
+      if (variableValuesMapping.ContainsKey(originalValues)) {
+        matchingValues = variableValuesMapping[originalValues];
+        return true;
+      }
+      matchingValues = variableValuesMapping.FirstOrDefault(kv => kv.Key == kv.Value && EqualVariableValues(originalValues, kv.Key)).Key;
+      bool result = true;
+      if (matchingValues == null) {
+        matchingValues = originalValues;
+        result = false;
+      }
+      variableValuesMapping[originalValues] = matchingValues;
+      return result;
+    }
+
+    private static bool EqualVariableValues(ValuesType values1, ValuesType values2) {
+      //compare variable names for equality
+      if (!values1.Keys.SequenceEqual(values2.Keys)) return false;
+      foreach (var key in values1.Keys) {
+        var v1 = values1[key];
+        var v2 = values2[key];
+        if (v1.Count != v2.Count) return false;
+        for (int i = 0; i < v1.Count; i++) {
+          if (!v1[i].Equals(v2[i])) return false;
+        }
+      }
+      return true;
     }
   }
