Julia 1.0 - Multi-dimensional Arrays

बहु आयामी Arrays




julia

बहु आयामी Arrays

जूलिया, अधिकांश तकनीकी कंप्यूटिंग भाषाओं की तरह, एक प्रथम श्रेणी सरणी कार्यान्वयन प्रदान करती है। अधिकांश तकनीकी कंप्यूटिंग भाषाएं अन्य कंटेनरों की कीमत पर उनके सरणी कार्यान्वयन पर बहुत ध्यान देती हैं। जूलिया किसी भी विशेष तरीके से सरणियों का इलाज नहीं करता है। सरणी लाइब्रेरी को जूलिया में लगभग पूरी तरह से लागू किया जाता है, और कंपाइलर से उसके प्रदर्शन को प्राप्त करता है, जैसे कि जूलिया में लिखा गया कोई अन्य कोड। जैसे, AbstractArray से विरासत में कस्टम सरणी प्रकारों को परिभाषित करना भी संभव है। कस्टम सरणी प्रकार को लागू करने के बारे में अधिक जानकारी के लिए AbstractArray इंटरफ़ेस पर मैनुअल अनुभाग देखें।

एक सरणी एक बहु-आयामी ग्रिड में संग्रहीत वस्तुओं का एक संग्रह है। सबसे सामान्य मामले में, एक सरणी में Any प्रकार की वस्तुएं हो सकती हैं। अधिकांश कम्प्यूटेशनल उद्देश्यों के लिए, सरणियों में अधिक विशिष्ट प्रकार की वस्तुएं होनी चाहिए, जैसे कि Float64 या Int32

सामान्य तौर पर, कई अन्य तकनीकी कंप्यूटिंग भाषाओं के विपरीत, जूलिया को उम्मीद नहीं है कि कार्यक्रम प्रदर्शन के लिए एक सदिश शैली में लिखे जाएंगे। जूलिया के कंपाइलर टाइप इंफ़ेक्शन का उपयोग करता है और स्केलर ऐरे इंडेक्सिंग के लिए अनुकूलित कोड बनाता है, जिससे प्रोग्राम को एक शैली में लिखा जा सकता है जो प्रदर्शन के बिना, सुविधाजनक और पठनीय होता है और कई बार कम मेमोरी का उपयोग करता है।

जूलिया में, कार्यों के सभी तर्क साझा करके (यानी संकेत द्वारा) पारित किए जाते हैं। कुछ तकनीकी कंप्यूटिंग भाषाएं मान द्वारा सरणियाँ पास करती हैं, और जबकि यह कॉलर में एक मूल्य के कैलीड द्वारा आकस्मिक संशोधन को रोकता है, यह सरणियों की अवांछित नकल से बचना मुश्किल बनाता है। अधिवेशन के द्वारा, एक समारोह का नाम एक के साथ समाप्त होता है ! यह इंगित करता है कि यह अपने एक या अधिक तर्कों के मूल्य को बदल देगा या नष्ट कर देगा (देखें, उदाहरण के लिए, sort और sort! । Callees को यह सुनिश्चित करने के लिए स्पष्ट प्रतियां बनाना चाहिए कि वे इनपुट को संशोधित नहीं करते हैं कि वे बदलने का इरादा नहीं रखते हैं। कई गैर-म्यूटिंग फ़ंक्शंस एक ही नाम के फ़ंक्शन को एक जोड़ा के साथ कॉल करके कार्यान्वित किया जाता है ! इनपुट की स्पष्ट प्रतिलिपि पर अंत में, और उस प्रतिलिपि को वापस लौटाता है।

बुनियादी कार्यों

समारोह विवरण
eltype(A) A में निहित तत्वों का प्रकार
length(A) A में तत्वों की संख्या
ndims(A) A के आयामों की संख्या
size(A) A के आयामों से युक्त एक tuple
size(A) आयाम के साथ A का आकार n
length(A) A के वैध सूचकांकों वाला एक टपल
length(A) आयाम n साथ मान्य सूचकांकों को व्यक्त करने वाली सीमा
eachindex(A) A में प्रत्येक स्थिति का दौरा करने के लिए एक कुशल पुनरावृत्ति
stride(A,k) स्ट्राइड (आयाम तत्वों के बीच रैखिक सूचकांक दूरी) आयाम k
strides(A) प्रत्येक आयाम में तारों का एक समूह

निर्माण और प्रारंभ

सरणियों के निर्माण और प्रारंभिक कार्य के लिए कई कार्य प्रदान किए जाते हैं। इस तरह के कार्यों की निम्नलिखित सूची में, dims... साथ कॉल dims... तर्क या तो आयाम आकारों के एक एकल टपल ले सकते हैं या आयाम आकारों की एक श्रृंखला को तर्कों की एक चर संख्या के रूप में पारित किया जाता है। इनमें से अधिकांश फ़ंक्शन एक पहला इनपुट T भी स्वीकार करते हैं, जो कि सरणी का तत्व प्रकार है। यदि T टाइप छोड़ा गया है तो यह Float64 लिए डिफ़ॉल्ट होगा।

समारोह विवरण
Array{T}(undef, dims...) एक बिन बुलाए घने Array
zeros(T, dims...) सभी शून्य का एक Array
ones(T, dims...) सभी लोगों की एक Array
trues(dims...) सभी मूल्यों के साथ एक BitArray true
falses(dims...) सभी मूल्यों के साथ एक BitArray
reshape(A, dims...) एक सरणी जिसमें A के समान डेटा है, लेकिन विभिन्न आयामों के साथ
copy(A) कॉपी A
deepcopy(A) प्रतिलिपि A , पुनरावर्ती रूप से इसके तत्वों की प्रतिलिपि बनाना
similar(A, T, dims...) A (घने, विरल, आदि) के रूप में A ही प्रकार का एक गैर-व्यवस्थित सरणी, लेकिन निर्दिष्ट तत्व प्रकार और आयामों के साथ। दूसरे और तीसरे तर्क दोनों वैकल्पिक हैं, यदि छोड़ा गया है तो A के तत्व प्रकार और आयामों के लिए डिफ़ॉल्ट।
reinterpret(T, A) A रूप में A ही बाइनरी डेटा के साथ एक सरणी, लेकिन तत्व प्रकार T
rand(T, dims...) यादृच्छिक के साथ एक Array , iid [1] और आधे खुले अंतराल में समान रूप से वितरित मूल्य $ [0, 1) $
randn(T, dims...) यादृच्छिक, iid और सामान्य रूप से वितरित मान के साथ एक Array
Matrix{T}(I, m, n) m -by- n पहचान मैट्रिक्स
range(start, stop=stop, length=n) n लीनरीली स्पेल्ड एलिमेंट्स की रेंज start लेकर stop
fill!(A, x) सरणी A को मान x साथ भरें
fill(x, dims...) एक Array से भरा है मान x
[1]

स्वतंत्र रूप से और पहचान से वितरित iid

वाक्यविन्यास [A, B, C, ...] अपने तर्कों के 1-डी सरणी (वेक्टर) का निर्माण करता है। यदि सभी तर्कों में एक सामान्य पदोन्नति प्रकार होता है तो वे convert का उपयोग करके उस प्रकार में convert

विभिन्न तरीकों से हम इन निर्माणकर्ताओं को आयाम दे सकते हैं, निम्नलिखित उदाहरणों पर विचार करें:

julia> zeros(Int8, 2, 2)
2×2 Array{Int8,2}:
 0  0
 0  0

julia> zeros(Int8, (2, 2))
2×2 Array{Int8,2}:
 0  0
 0  0

julia> zeros((2, 2))
2×2 Array{Float64,2}:
 0.0  0.0
 0.0  0.0

यहाँ, (2, 2) एक Tuple

कड़ी

Arrays का निर्माण और निम्नलिखित कार्यों का उपयोग करके भी किया जा सकता है:

समारोह विवरण
cat(A...; dims=k) आयाम (ओं) के साथ इनपुट सरणियों के साथ k
vcat(A...) cat(A...; dims=1) लिए आशुलिपि cat(A...; dims=1)
hcat(A...) cat(A...; dims=2) लिए आशुलिपि cat(A...; dims=2)

इन कार्यों के लिए पारित स्केलर मानों को 1-तत्व सरणियों के रूप में माना जाता है। उदाहरण के लिए,

julia> vcat([1, 2], 3)
3-element Array{Int64,1}:
 1
 2
 3

julia> hcat([1 2], 3)
1×3 Array{Int64,2}:
 1  2  3

संयोजन कार्यों का उपयोग इतनी बार किया जाता है कि उनमें विशेष वाक्यविन्यास हो:

अभिव्यक्ति कॉल
[A; B; C; ...] vcat(A...)
[ABC ...] hcat(A...)
[AB; CD; ...] hvcat

hvcat दोनों आयाम 1 (अर्धविराम के साथ) और आयाम 2 (रिक्त स्थान के साथ) में hvcat । इस सिंटैक्स के इन उदाहरणों पर विचार करें:

julia> [[1; 2]; [3, 4]]
4-element Array{Int64,1}:
 1
 2
 3
 4

julia> [[1 2] [3 4]]
1×4 Array{Int64,2}:
 1  2  3  4

julia> [[1 2]; [3 4]]
2×2 Array{Int64,2}:
 1  2
 3  4

टाइप ऐरर इनिशियलाइज़र

सिंटेक्स T[A, B, C, ...] का उपयोग करके एक विशिष्ट तत्व प्रकार के साथ एक सरणी का निर्माण किया जा सकता है। यह तत्व प्रकार T साथ 1-डी सरणी का निर्माण करेगा, जिसमें तत्व A , B , C आदि शामिल हैं। उदाहरण के लिए, Any[x, y, z] एक विषम सरणी का निर्माण करता है जिसमें कोई भी मान हो सकता है।

नतीजे के प्रकार को निर्दिष्ट करने के लिए एक प्रकार के साथ संयोजन वाक्य रचना को पहले से उपसर्ग किया जा सकता है।

julia> [[1 2] [3 4]]
1×4 Array{Int64,2}:
 1  2  3  4

julia> Int8[[1 2] [3 4]]
1×4 Array{Int8,2}:
 1  2  3  4

comprehensions

सरणियों के निर्माण के लिए समझदारी एक सामान्य और शक्तिशाली तरीका प्रदान करती है। गणित में निर्माण संकेतन सेट के समान है।

A = [ F(x,y,...) for x=rx, y=ry, ... ]

इस फॉर्म का अर्थ यह है कि F(x,y,...) का मूल्यांकन चर, x , y , आदि के साथ उनके दिए गए मूल्यों की सूची में प्रत्येक मूल्य पर किया जाता है। मूल्यों को किसी भी चलने योग्य वस्तु के रूप में निर्दिष्ट किया जा सकता है, लेकिन आमतौर पर 1:n या 2:(n-1) , या मानों की स्पष्ट सरणियों जैसे [1.2, 3.4, 5.7] सीमा होगी। परिणाम एक एनडी घने सरणी है जिसमें आयाम हैं जो चर श्रेणियों rx , ry , आदि के आयाम हैं और प्रत्येक F(x,y,...) मूल्यांकन एक अदिश रिटर्न देता है।

निम्न उदाहरण वर्तमान तत्व के भारित औसत और 1-डी ग्रिड के साथ उसके बाएं और दाएं पड़ोसी की गणना करता है। :

julia> x = rand(8)
8-element Array{Float64,1}:
 0.843025
 0.869052
 0.365105
 0.699456
 0.977653
 0.994953
 0.41084
 0.809411

julia> [ 0.25*x[i-1] + 0.5*x[i] + 0.25*x[i+1] for i=2:length(x)-1 ]
6-element Array{Float64,1}:
 0.736559
 0.57468
 0.685417
 0.912429
 0.8446
 0.656511

परिणामी सरणी प्रकार गणना किए गए तत्वों के प्रकारों पर निर्भर करता है। प्रकार को स्पष्ट रूप से नियंत्रित करने के लिए, एक प्रकार को समझ के लिए तैयार किया जा सकता है। उदाहरण के लिए, हम लिखकर एकल परिशुद्धता में परिणाम का अनुरोध कर सकते थे:

Float32[ 0.25*x[i-1] + 0.5*x[i] + 0.25*x[i+1] for i=2:length(x)-1 ]

जेनरेटर एक्सप्रेशंस

संलग्नक वर्ग कोष्ठक के बिना भी समझ लिखी जा सकती है, एक जनरेटर के रूप में जानी जाने वाली वस्तु का उत्पादन। यह ऑब्जेक्ट किसी सरणी को आवंटित करने और उन्हें पहले से संग्रहीत करने के बजाय ( Iteration देखें) माँग पर मान उत्पन्न करने के लिए पुनरावृत्त हो सकता है। उदाहरण के लिए, निम्नलिखित अभिव्यक्ति स्मृति को आवंटित किए बिना एक श्रृंखला प्रस्तुत करती है:

julia> sum(1/n^2 for n=1:1000)
1.6439345666815615

एक तर्क सूची के अंदर कई आयामों के साथ एक जनरेटर अभिव्यक्ति लिखते समय, जनरेटर को बाद के तर्कों से जनरेटर को अलग करने की आवश्यकता होती है:

julia> map(tuple, 1/(i+j) for i=1:2, j=1:2, [1:4;])
ERROR: syntax: invalid iteration specification

सभी अल्पविराम द्वारा अलग किए गए भावों की व्याख्या श्रेणियों के रूप में की जाती है। कोष्ठक जोड़ने से हम map एक तीसरा तर्क जोड़ सकते हैं:

julia> map(tuple, (1/(i+j) for i=1:2, j=1:2), [1 3; 2 4])
2×2 Array{Tuple{Float64,Int64},2}:
 (0.5, 1)       (0.333333, 3)
 (0.333333, 2)  (0.25, 4)

जनरेटर को आंतरिक कार्यों के माध्यम से कार्यान्वित किया जाता है। जैसा कि भाषा में आंतरिक कार्यों के अन्य मामलों में, एन्कोडिंग स्कोप से चर आंतरिक फ़ंक्शन में "कैप्चर" किया जा सकता है। उदाहरण के लिए, sum(p[i] - q[i] for i=1:n) तीन वैरिएबल p , q और n को कैप्चरिंग स्कोप से कैप्चर करता है। कैप्चर किए गए चर प्रदर्शन युक्तियों में वर्णित प्रदर्शन चुनौतियों को प्रस्तुत कर सकते हैं

जनरेटर और समझ में रंग for कीवर्ड के for कई लिखकर पिछली सीमाओं पर निर्भर कर सकते हैं:

julia> [(i,j) for i=1:3 for j=1:i]
6-element Array{Tuple{Int64,Int64},1}:
 (1, 1)
 (2, 1)
 (2, 2)
 (3, 1)
 (3, 2)
 (3, 3)

ऐसे मामलों में, परिणाम हमेशा 1-डी होता है।

यदि उत्पन्न कीवर्ड का उपयोग करके उत्पन्न मानों को फ़िल्टर किया जा सकता है:

julia> [(i,j) for i=1:3 for j=1:i if i+j == 4]
2-element Array{Tuple{Int64,Int64},1}:
 (2, 2)
 (3, 1)

इंडेक्सिंग

एक n- आयामी सरणी A में अनुक्रमण के लिए सामान्य वाक्यविन्यास है:

X = A[I_1, I_2, ..., I_n]

जहां प्रत्येक I_k एक स्केलर पूर्णांक, पूर्णांक का एक सरणी या किसी अन्य समर्थित सूचकांक हो सकता है । इसमें संपूर्ण आयाम के भीतर सभी सूचकांकों का चयन करने के लिए Colon (:) शामिल हैं a:c प्रपत्र की सीमाएं a:c या a:b:c का चयन करने के लिए सन्निहित या तार वाले उपखंडों का चयन करें, और अपने true सूचकांकों में तत्वों का चयन करने के लिए बूलियन के सरणियों।

यदि सभी सूचकांक स्केलर हैं, तो परिणाम X A सरणी से एक एकल तत्व है। अन्यथा, X सभी सूचकांकों के आयामों के योग के समान आयामों के साथ एक सरणी है।

यदि सभी सूचकांक वैक्टर हैं, उदाहरण के लिए, तो X का आकार होगा (length(I_1), length(I_2), ..., length(I_n)) , स्थान (i_1, i_2, ..., i_n) X का मान A[I_1[i_1], I_2[i_2], ..., I_n[i_n]]

उदाहरण:

julia> A = reshape(collect(1:16), (2, 2, 2, 2))
2×2×2×2 Array{Int64,4}:
[:, :, 1, 1] =
 1  3
 2  4

[:, :, 2, 1] =
 5  7
 6  8

[:, :, 1, 2] =
  9  11
 10  12

[:, :, 2, 2] =
 13  15
 14  16

julia> A[1, 2, 1, 1] # all scalar indices
3

julia> A[[1, 2], [1], [1, 2], [1]] # all vector indices
2×1×2×1 Array{Int64,4}:
[:, :, 1, 1] =
 1
 2

[:, :, 2, 1] =
 5
 6

julia> A[[1, 2], [1], [1, 2], 1] # a mix of index types
2×1×2 Array{Int64,3}:
[:, :, 1] =
 1
 2

[:, :, 2] =
 5
 6

ध्यान दें कि पिछले दो मामलों में परिणामी सरणी का आकार अलग कैसे है।

यदि I_1 को द्वि-आयामी मैट्रिक्स में बदल दिया जाता है, तो X आकार का एक n+1 -आयामी आयाम (size(I_1, 1), size(I_1, 2), length(I_2), ..., length(I_n)) । मैट्रिक्स एक आयाम जोड़ता है।

उदाहरण:

julia> A = reshape(collect(1:16), (2, 2, 2, 2));

julia> A[[1 2; 1 2]]
2×2 Array{Int64,2}:
 1  2
 1  2

julia> A[[1 2; 1 2], 1, 2, 1]
2×2 Array{Int64,2}:
 5  6
 5  6

स्थान (i_1, i_2, i_3, ..., i_{n+1}) में A[I_1[i_1, i_2], I_2[i_3], ..., I_n[i_{n+1}]] । स्केलर के साथ अनुक्रमित सभी आयामों को गिरा दिया जाता है। उदाहरण के लिए, A[2, I, 3] का परिणाम आकार size(I) साथ एक सरणी है। इसका i th तत्व A[2, I[i], 3] से आबाद है।

इस सिंटैक्स के एक विशेष भाग के रूप में, इंडेक्स कीवर्ड का उपयोग अनुक्रमण कोष्ठक के भीतर प्रत्येक आयाम के अंतिम सूचकांक का प्रतिनिधित्व करने के लिए किया जा सकता है, जैसा कि अंतरतम सरणी के आकार द्वारा अनुक्रमित किया जाता है। end कीवर्ड के बिना सिंटैक्स अनुक्रमण getindex लिए एक कॉल के getindex :

X = getindex(A, I_1, I_2, ..., I_n)

उदाहरण:

julia> x = reshape(1:16, 4, 4)
4×4 reshape(::UnitRange{Int64}, 4, 4) with eltype Int64:
 1  5   9  13
 2  6  10  14
 3  7  11  15
 4  8  12  16

julia> x[2:3, 2:end-1]
2×2 Array{Int64,2}:
 6  10
 7  11

julia> x[1, [2 3; 4 1]]
2×2 Array{Int64,2}:
  5  9
 13  1

प्रपत्र n:n-1 की खाली श्रेणियां कभी n:n-1 कभी n-1 और n बीच अंतर-सूचकांक स्थान को इंगित करने के लिए उपयोग की जाती हैं। उदाहरण के लिए, searchsorted फ़ंक्शन इस कन्वेंशन का उपयोग सॉर्ट किए गए एरे में पाए गए मान के सम्मिलन बिंदु को इंगित करने के लिए करता है:

julia> a = [1,2,5,6,7];

julia> searchsorted(a, 3)
3:2

असाइनमेंट

एन-आयामी सरणी A में मान निर्दिष्ट करने के लिए सामान्य वाक्यविन्यास है:

A[I_1, I_2, ..., I_n] = X

जहां प्रत्येक I_k एक स्केलर पूर्णांक, पूर्णांक का एक सरणी या किसी अन्य समर्थित सूचकांक हो सकता है । इसमें संपूर्ण आयाम के भीतर सभी सूचकांकों का चयन करने के लिए Colon (:) शामिल हैं a:c प्रपत्र की सीमाएं a:c या a:b:c का चयन करने के लिए सन्निहित या तार वाले उपखंडों का चयन करें, और अपने true सूचकांकों में तत्वों का चयन करने के लिए बूलियन के सरणियों।

यदि X एक सरणी है, तो इसमें सूचक तत्वों की लंबाई के उत्पाद के समान तत्व होने चाहिए: prod(length(I_1), length(I_2), ..., length(I_n)) । स्थान I_1[i_1], I_2[i_2], ..., I_n[i_n] A का I_1[i_1], I_2[i_2], ..., I_n[i_n] मान X[i_1, i_2, ..., i_n] साथ अधिलेखित है। यदि X कोई सरणी नहीं है, तो इसका मान A सभी संदर्भित स्थानों पर लिखा जाता है।

Indexing , इंडेक्स कीवर्ड का उपयोग इंडेक्सिंग कोष्ठक के भीतर प्रत्येक आयाम के अंतिम सूचकांक का प्रतिनिधित्व करने के लिए किया जा सकता है, जैसा कि सरणी के आकार द्वारा निर्धारित किया जा रहा है। end कीवर्ड के बिना अनुक्रमित असाइनमेंट सिंटैक्स setindex! लिए एक कॉल के setindex! :

setindex!(A, X, I_1, I_2, ..., I_n)

उदाहरण:

julia> x = collect(reshape(1:9, 3, 3))
3×3 Array{Int64,2}:
 1  4  7
 2  5  8
 3  6  9

julia> x[3, 3] = -9;

julia> x[1:2, 1:2] = [-1 -4; -2 -5];

julia> x
3×3 Array{Int64,2}:
 -1  -4   7
 -2  -5   8
  3   6  -9

समर्थित सूचकांक प्रकार

अभिव्यक्ति A[I_1, I_2, ..., I_n] , प्रत्येक I_k एक स्केलर इंडेक्स, स्केलर इंडेक्स की एक सरणी, या एक ऑब्जेक्ट हो सकता है, जो स्केलर इंडेक्स की एक सरणी का प्रतिनिधित्व करता है और इस तरह के to_indices परिवर्तित किया जा सकता है:

  1. एक अदिश सूचकांक। डिफ़ॉल्ट रूप से इसमें शामिल हैं:
    • गैर-बूलियन पूर्णांक
    • CartesianIndex{N} s, जो कई आयामों को फैलाने वाले पूर्णांकों के एक Ntuple की तरह व्यवहार करता है (अधिक विवरण के लिए नीचे देखें)
  2. स्केलर सूचकांकों की एक सरणी। यह भी शामिल है:
    • पूर्णांकों के वैक्टर और बहुआयामी सरणियाँ
    • खाली एरे जैसे [] , जो कोई तत्व नहीं चुनते हैं
    • रंग जैसे a:c या a:b:c , जो a से c (सम्मिलित) से सन्निहित या तार वाले उपखंडों का चयन करते हैं
    • स्केलर सूचकांकों का कोई कस्टम सरणी जो AbstractArray का एक उपप्रकार है
    • CartesianIndex{N} की CartesianIndex{N} (अधिक विवरण के लिए नीचे देखें)
  3. एक ऑब्जेक्ट जो स्केलर सूचक की एक सरणी का प्रतिनिधित्व करता है और इस तरह के to_indices परिवर्तित किया जा सकता है। डिफ़ॉल्ट रूप से इसमें शामिल हैं:
    • Colon ( Colon , जो पूरे आयाम के भीतर या पूरे सरणी में सभी सूचकांकों का प्रतिनिधित्व करता है
    • बूलियनों की सरणियाँ, जो अपने true सूचकांकों में तत्वों का चयन करती हैं (अधिक विवरण के लिए नीचे देखें)

कुछ उदाहरण:

julia> A = reshape(collect(1:2:18), (3, 3))
3×3 Array{Int64,2}:
 1   7  13
 3   9  15
 5  11  17

julia> A[4]
7

julia> A[[2, 5, 8]]
3-element Array{Int64,1}:
  3
  9
 15

julia> A[[1 4; 3 8]]
2×2 Array{Int64,2}:
 1   7
 5  15

julia> A[[]]
0-element Array{Int64,1}

julia> A[1:2:5]
3-element Array{Int64,1}:
 1
 5
 9

julia> A[2, :]
3-element Array{Int64,1}:
  3
  9
 15

julia> A[:, 3]
3-element Array{Int64,1}:
 13
 15
 17

कार्तीय संकेत

विशेष CartesianIndex{N} ऑब्जेक्ट एक स्केलर इंडेक्स का प्रतिनिधित्व करता है, जो कई आयामों के फैले पूर्णांकों के N टपल की तरह व्यवहार करता है। उदाहरण के लिए:

julia> A = reshape(1:32, 4, 4, 2);

julia> A[3, 2, 1]
7

julia> A[CartesianIndex(3, 2, 1)] == A[3, 2, 1] == 7
true

अकेले माना जाता है, यह अपेक्षाकृत तुच्छ लग सकता है; CartesianIndex बस एक ही वस्तु में कई पूर्णांकों को इकट्ठा करता है जो एक एकल बहुआयामी सूचकांक का प्रतिनिधित्व करता है। जब अन्य अनुक्रमण रूपों और पुनरावृत्तियों के साथ संयुक्त होता है, जो CartesianIndex तों CartesianIndex , हालांकि, यह सीधे बहुत ही सुरुचिपूर्ण और कुशल कोड को जन्म दे सकता है। नीचे Iteration देखें, और कुछ और उन्नत उदाहरणों के लिए, इस ब्लॉग पोस्ट को बहुआयामी एल्गोरिदम और पुनरावृत्ति पर देखें

CartesianIndex{N} की Arrays भी समर्थित हैं। वे स्केलर सूचकांकों के एक संग्रह का प्रतिनिधित्व करते हैं, जो कि प्रत्येक अवधि N आयाम, अनुक्रमण के एक रूप को सक्षम करता है जिसे कभी-कभी पॉइंटवाइज़ इंडेक्सिंग कहा जाता है। उदाहरण के लिए, यह ऊपर से पहले के "पृष्ठ" से विकर्ण तत्वों तक पहुंचने में सक्षम बनाता है:

julia> page = A[:,:,1]
4×4 Array{Int64,2}:
 1  5   9  13
 2  6  10  14
 3  7  11  15
 4  8  12  16

julia> page[[CartesianIndex(1,1),
             CartesianIndex(2,2),
             CartesianIndex(3,3),
             CartesianIndex(4,4)]]
4-element Array{Int64,1}:
  1
  6
 11
 16

इसे डॉट ब्रॉडकास्टिंग के साथ और सामान्य पूर्णांक सूचकांक के साथ संयोजन करके ( A से पहला page को एक अलग चरण के रूप में निकालने के बजाय) बहुत अधिक व्यक्त किया जा सकता है। इसे एक साथ भी जोड़ा जा सकता है : एक ही समय में दो पन्नों से दोनों विकर्ण निकालने के लिए:

julia> A[CartesianIndex.(axes(A, 1), axes(A, 2)), 1]
4-element Array{Int64,1}:
  1
  6
 11
 16

julia> A[CartesianIndex.(axes(A, 1), axes(A, 2)), :]
4×2 Array{Int64,2}:
  1  17
  6  22
 11  27
 16  32
चेतावनी

CartesianIndex और CartesianIndex सरणियाँ किसी आयाम के अंतिम सूचकांक का प्रतिनिधित्व करने के लिए अंतिम कीवर्ड के साथ संगत नहीं हैं। इंडेक्सिंग अभिव्यक्तियों में end का उपयोग न करें जिसमें CartesianIndex हो सकता है या इसके CartesianIndex हो सकते हैं।

तार्किक अनुक्रमण

अक्सर एक तार्किक मुखौटा के साथ तार्किक अनुक्रमण या अनुक्रमण के रूप में संदर्भित किया जाता है, बूलियन सरणी द्वारा अनुक्रमण उन सूचकांकों पर तत्वों का चयन करता है जहां इसके मूल्य true । बूलियन वेक्टर B द्वारा अनुक्रमण प्रभावी रूप से पूर्णांक के वेक्टर द्वारा अनुक्रमण के रूप में ही होता है जो कि length(A) द्वारा लौटाया जाता है। इसी प्रकार, N -डायमेंशनल बूलियन एरे द्वारा अनुक्रमण प्रभावी रूप से CartesianIndex{N} के वेक्टर द्वारा अनुक्रमण के समान है, जहां इसके मूल्य true । एक लॉजिकल इंडेक्स उसी लंबाई का वेक्टर होना चाहिए जिस आयाम में वह इंडेक्स करता है, या यह केवल प्रदान किया जाने वाला इंडेक्स होना चाहिए और यह जिस इंडेक्स में स्थित होता है उसके आकार और आयाम से मेल खाता है। यह आम तौर पर पहले कॉलिंग length(A) बजाय सूचक के रूप में बूलियन सरणियों का उपयोग करने के लिए अधिक कुशल है।

julia> x = reshape(1:16, 4, 4)
4×4 reshape(::UnitRange{Int64}, 4, 4) with eltype Int64:
 1  5   9  13
 2  6  10  14
 3  7  11  15
 4  8  12  16

julia> x[[false, true, true, false], :]
2×4 Array{Int64,2}:
 2  6  10  14
 3  7  11  15

julia> mask = map(ispow2, x)
4×4 Array{Bool,2}:
  true  false  false  false
  true  false  false  false
 false  false  false  false
  true   true  false   true

julia> x[mask]
5-element Array{Int64,1}:
  1
  2
  4
  8
 16

यात्रा

एक पूरे सरणी पर पुनरावृति करने के लिए अनुशंसित तरीके हैं

for a in A
    # Do something with the element a
end

for i in eachindex(A)
    # Do something with i and/or A[i]
end

पहले निर्माण का उपयोग तब किया जाता है जब आपको प्रत्येक तत्व के मूल्य की आवश्यकता होती है, लेकिन सूचकांक की नहीं। दूसरे निर्माण में, i एक Int यदि A एक प्रकार का प्रकार है जिसमें तेजी से रैखिक अनुक्रमण होता है; अन्यथा, यह CartesianIndex :

julia> A = rand(4,3);

julia> B = view(A, 1:3, 2:3);

julia> for i in eachindex(B)
           @show i
       end
i = CartesianIndex(1, 1)
i = CartesianIndex(2, 1)
i = CartesianIndex(3, 1)
i = CartesianIndex(1, 2)
i = CartesianIndex(2, 2)
i = CartesianIndex(3, 2)

for i = 1:length(A) विपरीत, eachindex(A) साथ पुनरावृत्ति किसी भी सरणी प्रकार पर पुनरावृति करने के लिए एक कुशल तरीका प्रदान करता है।

सरणी लक्षण

यदि आप एक कस्टम AbstractArray प्रकार लिखते हैं, तो आप यह निर्दिष्ट कर सकते हैं कि इसका उपयोग तेजी से रैखिक अनुक्रमण है

Base.IndexStyle(::Type{<:MyArray}) = IndexLinear()

यह सेटिंग पूर्णांक का उपयोग करने के लिए eachindex पर eachindex पुनरावृत्ति का कारण eachindex । यदि आप इस विशेषता को निर्दिष्ट नहीं करते हैं, तो डिफ़ॉल्ट मान IndexCartesian() का उपयोग किया जाता है।

ऐरे और वेक्टर ऑपरेटर्स और फ़ंक्शंस

निम्न ऑपरेटरों को सरणियों के लिए समर्थन दिया जाता है:

  1. असमान अंकगणित - - , +
  2. बाइनरी अंकगणित - - , + , * , / , \ , ^
  3. तुलना - == ; != isapprox ( isapprox )

गणितीय और अन्य परिचालनों के सुविधाजनक वेक्टरकरण को सक्षम करने के लिए, जूलिया एरे और स्केलर के सरणियों या मिश्रणों पर एलिमेंट्री ऑपरेशंस के लिए डॉट सिंटैक्स f.(args...) , उदाहरण के लिए sin.(x) या min.(x,y) प्रदान करता है। (एक Broadcasting ऑपरेशन); जब अन्य डॉट कॉल्स, जैसे sin.(cos.(x)) के साथ संयुक्त होने पर एक ही लूप में "फ़्यूज़िंग" का अतिरिक्त लाभ होता है।

साथ ही, प्रत्येक बाइनरी ऑपरेटर एक डॉट संस्करण का समर्थन करता है, जिसे इस तरह के फ़्यूज़ ब्रॉडकास्टिंग ऑपरेशनों में सरणियों (और सरणियों और स्केलरों के संयोजन) पर लागू किया जा सकता है, जैसे z .== sin.(x .* y)

ध्यान दें कि जैसे == पूरे एरेज़ पर काम करते हैं, एक एकल बूलियन जवाब देते हैं। डॉट संचालकों का उपयोग करें .== तत्व की तुलना के लिए। ( < , केवल एलिमेंट वाइज जैसे तुलनात्मक संचालन के लिए .< अरे संस्करण सरणियों के लिए लागू है।)

max.(a,b) बीच के अंतर को भी नोटिस करें, जो a और b पर max तत्व को broadcast , और maximum(a) , जो a भीतर सबसे बड़ा मूल्य पाता a । वही संबंध min.(a,b) और minimum(a)

प्रसारण

कभी-कभी विभिन्न आकारों के सरणियों पर तत्व-दर-तत्व द्विआधारी संचालन करना उपयोगी होता है, जैसे कि मैट्रिक्स के प्रत्येक स्तंभ में एक वेक्टर जोड़ना। ऐसा करने का एक अक्षम तरीका वेक्टर के मैट्रिक्स के आकार को दोहराने के लिए होगा:

julia> a = rand(2,1); A = rand(2,3);

julia> repeat(a,1,3)+A
2×3 Array{Float64,2}:
 1.20813  1.82068  1.25387
 1.56851  1.86401  1.67846

यह आयाम बेकार है जब आयाम बड़े हो जाते हैं, इसलिए जूलिया broadcast प्रदान करता broadcast , जो अतिरिक्त मेमोरी का उपयोग किए बिना अन्य सरणी में संबंधित आयाम से मेल खाने के लिए सरणी तर्कों में सिंगलटन आयाम का विस्तार करता है, और दिए गए फ़ंक्शन तत्व को लागू करता है:

julia> broadcast(+, a, A)
2×3 Array{Float64,2}:
 1.20813  1.82068  1.25387
 1.56851  1.86401  1.67846

julia> b = rand(1,2)
1×2 Array{Float64,2}:
 0.867535  0.00457906

julia> broadcast(+, a, b)
2×2 Array{Float64,2}:
 1.71056  0.847604
 1.73659  0.873631

बिंदीदार ऑपरेटर जैसे .+ और .* broadcast कॉल के बराबर हैं (सिवाय इसके कि वे फ्यूज करें, जैसा कि नीचे वर्णित है)। एक broadcast! भी है broadcast! एक स्पष्ट गंतव्य को निर्दिष्ट करने के लिए कार्य (जिसे फ्यूज़िंग फैशन द्वारा .= असाइनमेंट में भी एक्सेस किया जा सकता है)। इसके अलावा, f.(args...) broadcast(f, args...) बराबर है broadcast(f, args...) , किसी भी फ़ंक्शन ( डॉट सिंटैक्स ) को प्रसारित करने के लिए एक सुविधाजनक सिंटैक्स प्रदान करता है। नेस्टेड "डॉट कॉल्स" f.(...) (कॉल्स टू .+ वगैरह) सहित स्वचालित रूप से एक ही broadcast कॉल में फ्यूज हो जाता है।

इसके अतिरिक्त, broadcast केवल सरणियों तक ही सीमित नहीं है (फ़ंक्शन प्रलेखन देखें), यह ट्यूपल्स को भी संभालता है और किसी भी तर्क को मानता है जो कि "स्केलर" के रूप में एक सरणी, ट्यूपल या Ref ( Ptr को छोड़कर) नहीं है।

julia> convert.(Float32, [1, 2])
2-element Array{Float32,1}:
 1.0
 2.0

julia> ceil.((UInt8,), [1.2 3.4; 5.6 6.7])
2×2 Array{UInt8,2}:
 0x02  0x04
 0x06  0x07

julia> string.(1:3, ". ", ["First", "Second", "Third"])
3-element Array{String,1}:
 "1. First"
 "2. Second"
 "3. Third"

कार्यान्वयन

जूलिया में आधार सरणी प्रकार अमूर्त प्रकार AbstractArray । यह आयाम N की संख्या और तत्व प्रकार T AbstractVector और AbstractMatrix 1-d और 2-d मामलों के लिए उपनाम हैं। AbstractArray वस्तुओं पर संचालन को उच्च स्तर के ऑपरेटरों और कार्यों का उपयोग करके परिभाषित किया जाता है, एक तरह से जो अंतर्निहित भंडारण से स्वतंत्र होता है। ये ऑपरेशन आम तौर पर किसी भी विशिष्ट सरणी कार्यान्वयन के लिए एक वापसी के रूप में सही ढंग से काम करते हैं।

AbstractArray प्रकार में कुछ भी शामिल है जैसे सरणी, और इसे लागू करना पारंपरिक सरणियों से काफी अलग हो सकता है। उदाहरण के लिए, तत्वों को संग्रहीत किए जाने के बजाय अनुरोध पर गणना की जा सकती है। हालांकि, किसी भी ठोस AbstractArray{T,N} प्रकार को आम तौर पर कम से कम size(A) (एक Int टपल length(A) ), length(A) और getindex length(A) AbstractArray{T,N} को लागू करना चाहिए; परिवर्तनशील सरणियों को setindex! भी लागू करना चाहिए setindex! । यह अनुशंसा की जाती है कि इन कार्यों में लगभग निरंतर समय जटिलता हो, या तकनीकी रूप से 1 (1) जटिलता हो, अन्यथा कुछ सरणी फ़ंक्शंस अप्रत्याशित रूप से धीमा हो सकते हैं। ठोस प्रकारों को भी आमतौर पर एक similar(A,T=eltype(A),dims=size(A)) विधि प्रदान करनी चाहिए, जो copy(A) और अन्य आउट-ऑफ-ऑपरेशन के लिए एक समान सरणी आवंटित करने के लिए उपयोग की जाती है। कोई फर्क नहीं पड़ता कि कैसे एक AbstractArray{T,N} को आंतरिक रूप से दर्शाया गया है, T पूर्णांक अनुक्रमणिका द्वारा लौटाई गई वस्तु का प्रकार है ( A[1, ..., 1] , जब A खाली नहीं है) और N की लंबाई होनी चाहिए tuple size(A) लौटा। कस्टम AbstractArray कार्यान्वयन को परिभाषित करने के बारे में अधिक जानकारी के लिए, इंटरफ़ेस अध्याय में सरणी इंटरफ़ेस गाइड देखें।

DenseArray , DenseArray का एक सार उपप्रकार है जिसमें सभी सरणियों को शामिल किया गया है जहाँ तत्वों को स्तंभ-प्रमुख क्रम में संचित रूप से संग्रहीत किया जाता है ( प्रदर्शन टिप्स में अतिरिक्त नोट देखें)। Array टाइप DenseArray Vector का एक विशिष्ट उदाहरण है और Matrix 1-d और 2-d मामलों के लिए उपनाम हैं। बहुत कम परिचालनों को विशेष रूप से Array से परे लागू किया जाता है जो कि सभी AbstractArrays लिए आवश्यक हैं; सरणी लाइब्रेरी का अधिकांश भाग सामान्य तरीके से कार्यान्वित किया जाता है जो सभी कस्टम सरणियों को समान व्यवहार करने की अनुमति देता है।

SubArray AbstractArray की एक SubArray है जो इसे कॉपी करके मूल सरणी के साथ मेमोरी साझा करके अनुक्रमण करता है। एक SubArray को view फ़ंक्शन के साथ बनाया जाता है, जिसे getindex (एक सरणी और सूचकांक तर्कों की एक श्रृंखला के साथ) के रूप में उसी तरह कहा जाता है। view का परिणाम getindex के परिणाम के समान दिखता है, सिवाय इसके कि डेटा जगह पर छोड़ दिया जाता है। view SubArray ऑब्जेक्ट में इनपुट इंडेक्स वैक्टर को SubArray है, जिसे बाद में मूल सरणी को अप्रत्यक्ष रूप से अनुक्रमित करने के लिए उपयोग किया जा सकता है। अभिव्यक्ति या कोड के ब्लॉक के सामने @views मैक्रो डालकर, किसी भी array[...] को उस अभिव्यक्ति में स्लाइस करने के बजाय एक SubArray व्यू बनाने के लिए परिवर्तित किया जाएगा।

BitArray s अंतरिक्ष-कुशल "पैक" बूलियन सरणियां हैं, जो बूलियन मूल्य के प्रति एक बिट स्टोर करती हैं। उनका उपयोग Array{Bool} एरेज़ (जो बूलियन मूल्य प्रति एक बाइट को स्टोर करता है) के समान किया जा सकता है, और क्रमशः Array(bitarray) और Array(bitarray) BitArray(array) माध्यम से / से परिवर्तित किया जा सकता है।

एक "तार" सरणी को नियमित रूप से ऑफसेट में निर्धारित तत्वों के साथ स्मृति में संग्रहीत किया जाता है, जैसे कि एक समर्थित isbits तत्व प्रकार के साथ एक उदाहरण बाहरी सी और फोरट्रान कार्यों को पारित किया जा सकता है जो इस मेमोरी लेआउट की अपेक्षा करते हैं। कठोर सरणियों को एक स्ट्राइड्स strides(A) विधि को परिभाषित करना चाहिए जो प्रत्येक आयाम के लिए "स्ट्राइड्स" का एक टपल देता है; प्रदान की गई stride(A,k) विधि इस tuple के भीतर k th तत्व को एक्सेस करती है। 1 द्वारा आयाम k के सूचकांक को length(A) हुए stride(A,k) द्वारा length(A) के सूचकांक i को बढ़ाया जाना चाहिए। यदि कोई सूचक रूपांतरण विधि Base.unsafe_convert(Ptr{T}, A) प्रदान की जाती है, तो मेमोरी लेआउट को इन Base.unsafe_convert(Ptr{T}, A) के समान होना चाहिए। DenseArray एक तारित सरणी का एक बहुत विशिष्ट उदाहरण है जहां तत्वों को सन्निहित रूप से व्यवस्थित किया जाता है, इस प्रकार यह अपने उपप्रकारों को स्ट्राइड्स की उपयुक्त परिभाषा प्रदान करता है। अधिक ठोस उदाहरण तार गाइड के लिए इंटरफ़ेस गाइड के भीतर पाए जा सकते हैं। StridedVector और StridedMatrix , अंतर्निहित सरणी प्रकारों में से कई के लिए सुविधाजनक उपनाम हैं, जिन्हें तार के सरणियों के रूप में माना जाता है, जो कि केवल सूचक और स्ट्रैड का उपयोग करके अत्यधिक ट्यून्ड और अनुकूलित BLAS और LAPACK फ़ंक्शंस को कॉल करने वाले विशेष कार्यान्वयन का चयन करने की अनुमति देता है।

निम्न उदाहरण किसी भी अस्थायी को बनाए बिना एक बड़े सरणी के एक छोटे खंड के क्यूआर अपघटन की गणना करता है, और सही लीड आयाम फ़ंक्शन के साथ उचित आयाम आकार और स्ट्राइड मापदंडों को कॉल करके।

julia> a = rand(10, 10)
10×10 Array{Float64,2}:
 0.517515  0.0348206  0.749042   0.0979679  …  0.75984     0.950481   0.579513
 0.901092  0.873479   0.134533   0.0697848     0.0586695   0.193254   0.726898
 0.976808  0.0901881  0.208332   0.920358      0.288535    0.705941   0.337137
 0.657127  0.0317896  0.772837   0.534457      0.0966037   0.700694   0.675999
 0.471777  0.144969   0.0718405  0.0827916     0.527233    0.173132   0.694304
 0.160872  0.455168   0.489254   0.827851   …  0.62226     0.0995456  0.946522
 0.291857  0.769492   0.68043    0.629461      0.727558    0.910796   0.834837
 0.775774  0.700731   0.700177   0.0126213     0.00822304  0.327502   0.955181
 0.9715    0.64354    0.848441   0.241474      0.591611    0.792573   0.194357
 0.646596  0.575456   0.0995212  0.038517      0.709233    0.477657   0.0507231

julia> b = view(a, 2:2:8,2:2:4)
4×2 view(::Array{Float64,2}, 2:2:8, 2:2:4) with eltype Float64:
 0.873479   0.0697848
 0.0317896  0.534457
 0.455168   0.827851
 0.700731   0.0126213

julia> (q, r) = qr(b);

julia> q
4×4 LinearAlgebra.QRCompactWYQ{Float64,Array{Float64,2}}:
 -0.722358    0.227524  -0.247784    -0.604181
 -0.0262896  -0.575919  -0.804227     0.144377
 -0.376419   -0.75072    0.540177    -0.0541979
 -0.579497    0.230151  -0.00552346   0.781782

julia> r
2×2 Array{Float64,2}:
 -1.20921  -0.383393
  0.0      -0.910506