diff --git a/tree/treeplayer/inc/ROOT/TDFActionHelpers.hxx b/tree/treeplayer/inc/ROOT/TDFActionHelpers.hxx
index 221606401434bddd3875c4c91fad6dfd85bb11de..39a3685efc4dfdfe626134792f021304c0ae9c7f 100644
--- a/tree/treeplayer/inc/ROOT/TDFActionHelpers.hxx
+++ b/tree/treeplayer/inc/ROOT/TDFActionHelpers.hxx
@@ -248,8 +248,15 @@ public:
    HIST &PartialUpdate(unsigned int slot) { return *fTo->GetAtSlotRaw(slot); }
 };
 
-// IMPORTANT NOTE: changes to this class should probably be replicated in its partial specialization below
-template <typename T, typename COLL>
+// In case of the take helper we have 4 cases:
+// 1. The column is not an array_view, the collection is not a vector
+// 2. The column is not an array_view, the collection is a vector
+// 3. The column is an array_view, the collection is not a vector
+// 4. The column is an array_view, the collection is a vector
+
+// Case 1.: The column is not an array_view, the collection is not a vector
+// No optimisations, no transformations: just copies.
+template <typename RealT_t, typename T, typename COLL>
 class TakeHelper {
    std::vector<std::shared_ptr<COLL>> fColls;
 
@@ -265,7 +272,7 @@ public:
 
    void InitSlot(TTreeReader *, unsigned int) {}
 
-   void Exec(unsigned int slot, T v) { fColls[slot]->emplace_back(v); }
+   void Exec(unsigned int slot, T& v) { fColls[slot]->emplace_back(v); }
 
    void Finalize()
    {
@@ -281,10 +288,10 @@ public:
    COLL &PartialUpdate(unsigned int slot) { return *fColls[slot].get(); }
 };
 
-// note: changes to this class should probably be replicated in its unspecialized
-// declaration above
-template <typename T>
-class TakeHelper<T, std::vector<T>> {
+// Case 2.: The column is not an array_view, the collection is a vector
+// Optimisations, no transformations: just copies.
+template <typename RealT_t, typename T>
+class TakeHelper<RealT_t, T, std::vector<T>> {
    std::vector<std::shared_ptr<std::vector<T>>> fColls;
 
 public:
@@ -303,8 +310,9 @@ public:
 
    void InitSlot(TTreeReader *, unsigned int) {}
 
-   void Exec(unsigned int slot, T v) { fColls[slot]->emplace_back(v); }
+   void Exec(unsigned int slot, T& v) { fColls[slot]->emplace_back(v); }
 
+   // This is optimised to treat vectors
    void Finalize()
    {
       ULong64_t totSize = 0;
@@ -320,6 +328,84 @@ public:
    std::vector<T> &PartialUpdate(unsigned int slot) { return *fColls[slot]; }
 };
 
+// Case 3.: The column is an array_view, the collection is not a vector
+// No optimisations, transformations from array_views to vectors
+template <typename RealT_t, typename COLL>
+class TakeHelper<RealT_t, std::array_view<RealT_t>, COLL> {
+   std::vector<std::shared_ptr<COLL>> fColls;
+
+public:
+   using BranchTypes_t = TypeList<std::array_view<RealT_t>>;
+   TakeHelper(const std::shared_ptr<COLL> &resultColl, const unsigned int nSlots)
+   {
+      fColls.emplace_back(resultColl);
+      for (unsigned int i = 1; i < nSlots; ++i) fColls.emplace_back(std::make_shared<COLL>());
+   }
+   TakeHelper(TakeHelper &&) = default;
+   TakeHelper(const TakeHelper &) = delete;
+
+   void InitSlot(TTreeReader *, unsigned int) {}
+
+   void Exec(unsigned int slot, std::array_view<RealT_t> av)
+   {
+      fColls[slot]->emplace_back(av.begin(), av.end());
+   }
+
+   void Finalize()
+   {
+      auto rColl = fColls[0];
+      for (unsigned int i = 1; i < fColls.size(); ++i) {
+         auto &coll = fColls[i];
+         for (auto &v : *coll) {
+            rColl->emplace_back(v);
+         }
+      }
+   }
+};
+
+// Case 4.: The column is an array_view, the collection is a vector
+// Optimisations, transformations from array_views to vectors
+template <typename RealT_t>
+class TakeHelper<RealT_t, std::array_view<RealT_t>, std::vector<RealT_t>> {
+   std::vector<std::shared_ptr<std::vector<std::vector<RealT_t>>>> fColls;
+
+public:
+   using BranchTypes_t = TypeList<std::array_view<RealT_t>>;
+   TakeHelper(const std::shared_ptr<std::vector<std::vector<RealT_t>>> &resultColl, const unsigned int nSlots)
+   {
+      fColls.emplace_back(resultColl);
+      for (unsigned int i = 1; i < nSlots; ++i) {
+         auto v = std::make_shared<std::vector<RealT_t>>();
+         v->reserve(1024);
+         fColls.emplace_back(v);
+      }
+   }
+   TakeHelper(TakeHelper &&) = default;
+   TakeHelper(const TakeHelper &) = delete;
+
+   void InitSlot(TTreeReader *, unsigned int) {}
+
+   void Exec(unsigned int slot, std::array_view<RealT_t> av)
+   {
+      fColls[slot]->emplace_back(av.begin(), av.end());
+   }
+
+   // This is optimised to treat vectors
+   void Finalize()
+   {
+      ULong64_t totSize = 0;
+      for (auto &coll : fColls) totSize += coll->size();
+      auto rColl = fColls[0];
+      rColl->reserve(totSize);
+      for (unsigned int i = 1; i < fColls.size(); ++i) {
+         auto &coll = fColls[i];
+         rColl->insert(rColl->end(), coll->begin(), coll->end());
+      }
+   }
+};
+
+
+
 template <typename F, typename T>
 class ReduceHelper {
    F fReduceFun;
diff --git a/tree/treeplayer/inc/ROOT/TDFInterface.hxx b/tree/treeplayer/inc/ROOT/TDFInterface.hxx
index 6ce3114b3f5ecc1f9597a2bca831f0c51e6a9ead..56ffe38a78e67837991174cd4bd51feb1e579b0b 100644
--- a/tree/treeplayer/inc/ROOT/TDFInterface.hxx
+++ b/tree/treeplayer/inc/ROOT/TDFInterface.hxx
@@ -56,12 +56,12 @@ using namespace ROOT::Detail::TDF;
 template <typename T>
 class CacheColumnHolder {
 public:
-   using value_type = T;
-   std::vector<T> fContent;
+   using value_type = T; // A shortcut to the value_type of the vector
+   std::vector<value_type> fContent;
    // This method returns a pointer since we treat these columns as if they come
    // from a data source, i.e. we forward an entry point to valid memory rather
    // than a value.
-   T *operator()(unsigned int /*slot*/, ULong64_t iEvent) { return &fContent[iEvent]; };
+   value_type *operator()(unsigned int /*slot*/, ULong64_t iEvent) { return &fContent[iEvent]; };
 };
 
 // ENDCACHE------------
@@ -236,6 +236,37 @@ void CallBuildAndBook(PrevNodeType &prevNode, const ColumnNames_t &bl, const uns
 } // namespace TDF
 } // namespace Internal
 
+namespace Detail {
+namespace TDF {
+
+template<typename T, typename COLL = std::vector<T>>
+struct TakeRealTypes {
+   // We cannot put in the output collection C arrays: the ownership is not defined.
+   // We therefore proceed to check if T is an array_view
+   // If yes, we check what type is the output collection and we rebuild it.
+   // E.g. if a vector<V> was the selected collection, where V is array_view<T>,
+   // the collection becomes vector<vector<T>>.
+   static constexpr auto isAV = TDFInternal::IsArrayView_t<T>::value;
+   using ValueType_t = typename TDFInternal::ValueType<T>::value_type;
+   using ValueTypeColl_t = std::vector<ValueType_t>;
+
+   using NewC0_t = typename std::conditional<isAV && TDFInternal::IsVector_t<COLL>::value,
+                                             std::vector<ValueTypeColl_t>,
+                                             COLL>::type;
+   using NewC1_t = typename std::conditional<isAV && TDFInternal::IsList_t<NewC0_t>::value,
+                                             std::list<ValueTypeColl_t>,
+                                             NewC0_t>::type;
+   using NewC2_t = typename std::conditional<isAV && TDFInternal::IsDeque_t<NewC1_t>::value,
+                                             std::deque<ValueTypeColl_t>,
+                                             NewC1_t>::type;
+
+   using RealT_t = typename std::conditional<isAV, ValueType_t, T>::type;
+   using RealColl_t = NewC2_t;
+};
+
+} // namespace TDF
+} // namespace Detail
+
 namespace Experimental {
 
 // forward declarations
@@ -844,7 +875,7 @@ public:
    /// This action is *lazy*: upon invocation of this method the calculation is
    /// booked but not executed. See TResultProxy documentation.
    template <typename T, typename COLL = std::vector<T>>
-   TResultProxy<COLL> Take(std::string_view column = "")
+   auto Take(std::string_view column = "") -> TResultProxy<typename TDFDetail::TakeRealTypes<T, COLL>::RealColl_t>
    {
       auto loopManager = GetDataFrameChecked();
       const auto columns = column.empty() ? ColumnNames_t() : ColumnNames_t({std::string(column)});
@@ -853,9 +884,13 @@ public:
       if (fDataSource)
          TDFInternal::DefineDataSourceColumns(validColumnNames, *loopManager, TDFInternal::GenStaticSeq_t<1>(),
                                               TTraits::TypeList<T>(), *fDataSource);
-      using Helper_t = TDFInternal::TakeHelper<T, COLL>;
+
+      using RealT_t = typename TDFDetail::TakeRealTypes<T, COLL>::RealT_t;
+      using RealColl_t = typename TDFDetail::TakeRealTypes<T, COLL>::RealColl_t;
+
+      using Helper_t = TDFInternal::TakeHelper<RealT_t, T, RealColl_t>;
       using Action_t = TDFInternal::TAction<Helper_t, Proxied>;
-      auto valuesPtr = std::make_shared<COLL>();
+      auto valuesPtr = std::make_shared<RealColl_t>();
       const auto nSlots = fProxiedPtr->GetNSlots();
       auto action = std::make_shared<Action_t>(Helper_t(valuesPtr, nSlots), validColumnNames, *fProxiedPtr);
       loopManager->Book(action);
@@ -1574,8 +1609,7 @@ private:
       // We share bits and pieces with snapshot. De facto this is a snapshot
       // in memory!
       TDFInternal::CheckSnapshot(sizeof...(BranchTypes), columnList.size());
-
-      std::tuple<TDFInternal::CacheColumnHolder<BranchTypes>...> colHolders;
+      std::tuple<TDFInternal::CacheColumnHolder<typename TDFDetail::TakeRealTypes<BranchTypes>::RealColl_t::value_type>...> colHolders;
 
       // TODO: really fix the type of the Take....
       std::initializer_list<int> expander0{(
diff --git a/tree/treeplayer/inc/ROOT/TDFUtils.hxx b/tree/treeplayer/inc/ROOT/TDFUtils.hxx
index 117a9e7045271134bd40d1c15ed46ed711dc49c4..9f70c0234933cc003e399ded779ecd1f4cd44522 100644
--- a/tree/treeplayer/inc/ROOT/TDFUtils.hxx
+++ b/tree/treeplayer/inc/ROOT/TDFUtils.hxx
@@ -21,11 +21,13 @@
 
 #include <array>
 #include <cstddef> // std::size_t
+#include <deque>
 #include <functional>
 #include <memory>
 #include <string>
 #include <type_traits> // std::decay
 #include <vector>
+
 class TTree;
 class TTreeReader;
 
@@ -316,6 +318,44 @@ struct TEvalAnd {
    static constexpr bool value = IsTrueForAllImpl_t<Conditions...>::value;
 };
 
+// Check if a class is a specialisation of stl containers templates
+
+template<typename>
+struct IsVector_t : std::false_type {};
+
+template<typename T>
+struct IsVector_t<std::vector<T>> : std::true_type {};
+
+template<typename>
+struct IsList_t : std::false_type {};
+
+template<typename T>
+struct IsList_t<std::list<T>> : std::true_type {};
+
+template<typename>
+struct IsDeque_t : std::false_type {};
+
+template<typename T>
+struct IsDeque_t<std::deque<T>> : std::true_type {};
+
+template<typename>
+struct IsArrayView_t : std::false_type {};
+
+template<typename T>
+struct IsArrayView_t<std::array_view<T>> : std::true_type {};
+
+// Check the value_type type of a type with a SFINAE to allow compilation in presence
+// fundamental types
+template<typename T, bool IsContainer = IsContainer<typename std::decay<T>::type>::value>
+struct ValueType {
+   using value_type = typename T::value_type;
+};
+
+template<typename T>
+struct ValueType<T, false> {
+   using value_type = T;
+};
+
 } // end NS TDF
 } // end NS Internal
 } // end NS ROOT