تقطيع المصفوفة

في برمجة الحاسوب ، تقطيع المصفوفة هو عملية تستخرج مجموعة فرعية من العناصر من مصفوفة وتعبئها كمصفوفة أخرى، ربما بأبعاد مختلفة عن المصفوفة الأصلية.

من الأمثلة الشائعة على تقطيع المصفوفات استخراج سلسلة فرعية من سلسلة من الأحرف، مثل " ell " في "h hello "، أو استخراج صف أو عمود من مصفوفة ثنائية الأبعاد، أو استخراج متجه من مصفوفة .

بحسب لغة البرمجة ، يمكن إنشاء شريحة من المصفوفة من عناصر غير متتالية. كما قد يتم، بحسب اللغة أيضاً، ربط عناصر المصفوفة الجديدة بعناصر المصفوفة الأصلية (أي مشاركتها في الذاكرة).

تفاصيل

بالنسبة للمصفوفات "أحادية البعد" (ذات الفهرسة الفردية) - مثل المتجهات والمتتاليات والسلاسل النصية وغيرها - فإن عملية التقطيع الأكثر شيوعًا هي استخراج صفر أو أكثر من العناصر المتتالية. فإذا كان لدينا متجه يحتوي على العناصر (2، 5، 7، 3، 8، 6، 4، 1)، وأردنا إنشاء شريحة من المصفوفة من العنصر الثالث إلى العنصر السادس، فسنحصل على (7، 3، 8، 6). أما في لغات البرمجة التي تستخدم نظام فهرسة يبدأ من الصفر، فستكون الشريحة من الفهرس 2 إلى الفهرس 5 .  

يؤدي تقليص نطاق أي فهرس إلى قيمة واحدة إلى إلغاء الحاجة إليه فعليًا. يمكن استخدام هذه الميزة، على سبيل المثال، لاستخراج شرائح أحادية البعد (متجهات في ثلاثة أبعاد، بما في ذلك الصفوف والأعمدة والأنابيب [ 1 ] ) أو شرائح ثنائية البعد (مصفوفات مستطيلة) من مصفوفة ثلاثية الأبعاد. مع ذلك، بما أنه يمكن تحديد النطاق أثناء التشغيل، فقد تتطلب اللغات التي تتحقق من أنواع البيانات استخدام صيغة صريحة (أثناء الترجمة) لحذف الفهارس غير الضرورية.

يمكن تنفيذ تقطيع المصفوفات العامة (سواءً كانت هذه الميزة مضمنة في اللغة أم لا) من خلال الإشارة إلى كل مصفوفة عبر متجه أو واصف (dope vector ) - وهو سجل يحتوي على عنوان العنصر الأول في المصفوفة، ثم نطاق كل فهرس والمعامل المقابل في صيغة الفهرسة. تتيح هذه التقنية أيضًا إمكانية تبديل المصفوفة مباشرةً ، وعكس الفهرس، وأخذ عينات فرعية، وما إلى ذلك. بالنسبة للغات مثل C ، حيث تبدأ الفهارس دائمًا من الصفر، يحتوي متجه المصفوفة ذي d فهرس على 1 + 2d من المعاملات على الأقل . أما بالنسبة للغات التي تسمح بحدود دنيا اختيارية للفهارس، مثل باسكال ، فيحتاج متجه المصفوفة إلى 1 + 3d من المدخلات. 

إذا لم يدعم تجريد المصفوفة الفهارس السالبة الحقيقية (كما هو الحال في مصفوفات لغتي Ada و Pascal )، فإنه يُستخدم أحيانًا فهارس سالبة لحدود الشريحة في بُعد معين لتحديد إزاحة من نهاية المصفوفة في ذلك البُعد. في الأنظمة التي تبدأ من 1، يشير -1 عمومًا إلى العنصر قبل الأخير، بينما في الأنظمة التي تبدأ من 0، يشير إلى العنصر الأخير.

تاريخ

كان مفهوم التقطيع معروفًا بالتأكيد حتى قبل اختراع المترجمات . وربما بدأ استخدام التقطيع كميزة لغوية مع لغة فورتران (1957)، كنتيجة لعدم وجود فحص للأنواع والنطاقات أكثر من كونه تصميمًا مقصودًا. كما أُشير إلى هذا المفهوم في التقرير التمهيدي لمعيار IAL (ALGOL 58) حيث سمحت الصيغة بحذف فهرس واحد أو أكثر لعنصر مصفوفة (أو حتى لاستدعاء إجراء) عند استخدامه كمعامل فعلي.

كانت لغة APL التي ابتكرها كينيث إيفرسون (1957) تتمتع بقدرة عالية على تقسيم المصفوفات متعددة الأبعاد، مما ساهم بشكل كبير في قوة اللغة التعبيرية وشعبيتها.

قدمت لغة ALGOL 68 (1968) ميزات شاملة لتقطيع وقص المصفوفات متعددة الأبعاد.

تم دمج إمكانيات تقطيع المصفوفات في العديد من اللغات الحديثة، مثل Ada و Cobra و D و Fortran 90 و Go و Rust و Julia و MATLAB و Perl و Python و S -Lang و Windows PowerShell واللغات الرياضية/الإحصائية GNU Octave و S و R.

الجدول الزمني لعملية التقطيع في لغات البرمجة المختلفة

1964: PL/I

يوفر PL/I ميزتين لتقسيم المصفوفة.

  • باستخدام تعريف iSub ، يمكن تعريف شريحة مصفوفة باستخدام متغيرات iSUB لربط عناصر محددة في "مصفوفة أساسية" بعناصر "المصفوفة المُعرَّفة". يمكن لـ iSUB تعريف الصفوف والأعمدة والأقطار، أو عمليات الربط من متعدد إلى واحد. [ 2 ] : ص 212-213. يُعرّف المثال التالي Yشريحة أحادية البعد تتكون من العناصر القطرية للمصفوفة ثنائية الأبعاد X.
أعلن X(5,5)؛ DECLARE Y(5) DEFINED(X(1SUB,1SUB));

الإشارة إلى شيء ما Y(2)هي إشارة إلى شيء آخر X(2,2)، وهكذا.

  • يمكن الإشارة إلى شريحة من مصفوفة، تُسمى مقطعًا عرضيًا ، باستخدام علامة النجمة (*) كدليل سفلي لبعد واحد أو أكثر. يقوم الكود التالي بتعيين جميع العناصر في العمود الأول من المصفوفة Xإلى الصفر. يمكن تحديد دليل سفلي واحد أو أكثر باستخدام علامات النجمة في التعبير. [ 2 ] : ص 43
أعلن X(5,5)؛ X(*,1)=0;

لم يتمكن مبرمجو لغة فورتران 66 إلا من الاستفادة من تقطيع المصفوفات حسب الصف، وذلك فقط عند تمرير ذلك الصف إلى روتين فرعي :

طباعة روتين فرعي V ( VEC , LEN ) REAL VEC ( * ) طباعة * , ( VEC ( I ) , I = 1 , LEN ) ENDPROGRAM MAIN PARAMETER ( LEN = 3 ) REAL MATRIX ( LEN , LEN ) DATA MATRIX / 1 , 1 , 1 , 2 , 4 , 8 , 3 , 9 , 27 / CALL PRINT V ( MATRIX ( 1 , 2 ), LEN ) END

نتيجة:

 2.000000 4.000000 8.000000

لاحظ أنه لا يوجد متجه dope في FORTRAN 66، وبالتالي يجب أيضًا تمرير طول الشريحة كوسيط - أو بأي وسيلة أخرى - إلى SUBROUTINE. في سبعينيات القرن العشرين، كانت لغتا باسكال وسي تفرضان قيودًا مماثلة.

يحتوي التقرير النهائي لـ Algol68 على مثال مبكر للتقطيع، ويتم تحديد الشرائح بالشكل التالي:

[الحد الأدنى: الحد الأعلى] ¢ لأجهزة الكمبيوتر ذات مجموعات الأحرف الموسعة ¢

أو:

(الحد الأدنى..الحد الأعلى) # لأجهزة الكمبيوتر التي تحتوي على أحرف 6 بت فقط. #

كلا الحدين شاملان ويمكن حذفهما، وفي هذه الحالة يتم استخدام حدود المصفوفة المعلنة افتراضيًا. لا تتضمن النسخة المعدلة من التقرير خاصية الخطوة ولا أسماء الشرائح القطرية المستعارة.

أمثلة:

[3, 3]real a := ((1, 1, 1), (2, 4, 8), (3, 9, 27)); # تعريف مصفوفة متغيرة # [,] real c = ((1, 1, 1), (2, 4, 8), (3, 9, 27)); # مصفوفة ثابتة، حجمها مُضمّن #
ref[]real row := a[2,]; # اسم مستعار/ مرجع لشريحة صف # ref[]real col2 = a[, 2]; # اسم مستعار/ مرجع دائم للعمود الثاني #
اطبع ((a[:, 2], سطر جديد)); # شريحة العمود الثاني # اطبع ((a[1⌈a, :], سطر جديد)); # شريحة الصف الأخير # اطبع ((a[:, 2⌈a], سطر جديد)); # شريحة العمود الأخير # اطبع ((a[:2, :2], سطر جديد)); # شريحة المصفوفة الفرعية 2×2 الرئيسية #
+1.0000 10 +0 +4.0000 10 +0 +9.0000 10 +0 +3.0000 10 +0 +9.0000 10 +0 +2.7000 10 +1 +1.0000 10 +0 +8.0000 10 +0 +2.7000 10 +1 +1.0000 10 +0 +1.0000 10 +0 +2.0000 10 +0 +4.0000 10 +0

1968: بيسك

استخدمت أنظمة HP 2000 من HP ، التي طُرحت في نوفمبر 1968، لغة البرمجة HP Time-Shared BASIC كواجهة أساسية لها. اعتمدت هذه النسخة من BASIC على تقنية التقطيع لمعظم عمليات معالجة النصوص. ومن غرائب ​​هذه اللغة أنها سمحت باستخدام الأقواس الدائرية والمربعة بشكل تبادلي، وكان نوع الأقواس المستخدمة عمليًا يعتمد عادةً على نوع جهاز الكمبيوتر المستخدم.

مثال:

10 A$ = "HELLO, WORLD" 20 PRINT A$ ( 1 , 5 ) 30 PRINT A$ [ 7 , 11 ]

سينتج:

مرحبا بالعالم

كانت أنظمة HP شائعة الاستخدام في أوائل سبعينيات القرن العشرين، لا سيما في المدارس الثانوية التقنية والعديد من المنشآت الصناعية والعلمية الصغيرة. [ 3 ] ومع ظهور الحواسيب الصغيرة الأولى في منتصف سبعينيات القرن العشرين، استُخدمت أنظمة HP كنموذج للغات BASIC الخاصة بها. ومن الأمثلة البارزة على ذلك Apple BASIC (1977)، و Atari BASIC ( 1978) ، و Sinclair BASIC (1979) . يوفر هذا الأسلوب في البرمجة مزايا عامة من حيث استخدام الذاكرة، وكان يُختار غالبًا في الأنظمة التي تأتي بذاكرة محدودة. وكانت لغة Sinclair هي الوحيدة التي اختلفت بشكل ملحوظ، حيث استخدمت الكلمة TOالمفتاحية بدلًا من قائمة مفصولة بفواصل.

10. ليت a$ = "ABCDE" ( 2 إلى 4 ) 20. اطبع a$

تم اختيار تقنية التقطيع أيضًا كأساس لمعيار ANSI Full BASIC ، باستخدام النقطتين كفاصل، وبالتالي التمييز بين التقطيع والوصول إلى المصفوفة:

10 DIM A$ ( 5 ) 20 LET A$ ( 2 ) = "HELLO, WORLD" 30 PRINT A$ ( 2 )( 1 : 5 )

رغم أن هذا الأسلوب في الوصول إلى البيانات قدّم العديد من المزايا، خاصةً للأجهزة الصغيرة في ذلك الوقت، إلا أنه بعد عام 1970 تقريبًا، قدّمت شركة ديجيتال إكويبمنت ( DEC ) نسختها الخاصة من لغة BASIC التي استخدمت دوالًا مثل LEFT$`.` RIGHT$و`.` و`.`. وقد كُتبت لغة مايكروسوفت BASIC على جهاز PDP-10 ، واستُخدمت كنموذج. وخلال أواخر السبعينيات، شاع استخدام كلا الأسلوبين، ولكن بحلول أوائل الثمانينيات، أصبحت دوال أسلوب DEC هي المعيار الفعلي .MID$

سبعينيات القرن العشرين: ماتلاب

>> A = round ( rand ( 3 , 4 , 5 ) * 10 ) % مصفوفة ثلاثية الأبعاد أو مكعبة 3×4× 5 >> A (:, :, 3 ) % مصفوفة ثنائية الأبعاد 3×4 على طول البعدين الأول والثانيans = 8 3 5 7  8 9 1 4  4 4 2 5>> A (:, 2 : 3 , 3 ) % مصفوفة ثنائية الأبعاد 3×2 على طول البعدين الأول والثانيans = 3 5  9 1  4 2>> A ( 2 : end , :, 3 ) % مصفوفة ثنائية الأبعاد 2x4 باستخدام الكلمة المفتاحية 'end'؛ تعمل مع GNU Octave 3.2.4ans = 6 1 4 6  10 1 3 1>> مصفوفة أحادية البعد ( 1 ، 3 ) على طول البعد الثانيans = 8 3 5 7>> A ( 1 , 2 , 3 ) % قيمة واحدة الإجابة = 3

يُنفّذ هذا :المُعامل صيغة الخطوة ( lower_bound:upper_bound[:stride]) عن طريق إنشاء متجه. 1:5يُقيّم كـ [1, 2, 3, 4, 5]. 1:9:2يُقيّم كـ [1, 3, 5, 7, 9]. :يُقيّم بشكل أساسي بنفس طريقة 1:end، مع endتحديد القيمة حسب السياق.

1976 : S / R

تُعتبر المصفوفات في S و GNU R دائمًا ذات ترقيم يبدأ من 1، وبالتالي ستبدأ فهارس الشريحة الجديدة من 1 لكل بُعد، بغض النظر عن الفهارس السابقة. سيتم حذف الأبعاد التي طولها 1 (إلا إذا كانت قيمة drop = FALSE). سيتم الاحتفاظ بأسماء الأبعاد (إن وجدت).

> A <- array ( 1 : 60 , dim = c ( 3 , 4 , 5 )) # مصفوفة ثلاثية الأبعاد أو مكعبة 3× 4×5 > A [, , 3 ] # مصفوفة ثنائية الأبعاد 3×4 على طول البعدين الأول والثاني  [, 1] [, 2] [, 3] [, 4] [ 1,] 25 28 31 34 [2,] 26 29 32 35 [3,] 27 30 33 36 > A [, 2 : 3 , 3 , drop = FALSE ] # مجموعة فرعية من مصفوفة مكعبة 3 ×2 ×1 (مع الحفاظ على الأبعاد) , , 1 [, 1] [, 2] [1,] 28 31 [2,] 29 32 [3,] 30 33 > A [, 2 , 3 ] # مصفوفة أحادية البعد على طول البعد الأول [1] 28 29 30 > A [ 1 , 2 , 3 ] # قيمة واحدة [1] 28

أدخل معيار Fortran 77 إمكانية تقطيع ودمج السلاسل النصية:

PROGRAM MAIN PRINT * , 'ABCDE' ( 2 : 4 ) END

ينتج:

BCD

يمكن تمرير هذه السلاسل بالإشارة إلى روتين فرعي آخر، وسيتم أيضًا تمرير الطول بشفافية إلى الروتين الفرعي كنوع من متجه dope قصير .

روتين فرعي PRINT S ( STR ) CHARACTER * ( * ) STR PRINT * , STR ENDPROGRAM MAIN CALL PRINT S ( 'ABCDE' ( 2 : 4 )) END

ينتج مرة أخرى:

BCD

1983: آدا 83 وما فوق

تدعم لغة Ada 83 الشرائح لجميع أنواع المصفوفات. ومثل لغة Fortran 77، يمكن تمرير هذه المصفوفات كمرجع إلى روتين فرعي آخر، كما يتم تمرير طولها بشفافية إلى الروتين الفرعي كنوع من متجه البيانات المختصر .

باستخدام Text_IO ؛الإجراء الرئيسي هو نص : سلسلة := "ABCDE" ; ابدأ Text_IO . Put_Line ( نص ( 2 .. 4 )); نهاية الرئيسي ;

ينتج:

BCD

ملاحظة: بما أن الفهارس في لغة Ada تعتمد على n، فإن المصطلح Text (2 .. 4)سينتج عنه مصفوفة بفهرس أساسي 2.

تعريف ذلك Text_IO.Put_Lineهو:

الحزمة Ada.Text_IO هيإجراء Put_Line ( العنصر : في سلسلة نصية );

تعريف ذلك Stringهو:

الحزمة القياسية هيالنوع الفرعي الموجب هو عدد صحيح، نطاقه 1 .. عدد صحيح ' الأخير ؛النوع String هو مصفوفة ( نطاق موجب <>) من الأحرف ؛ pragma Pack ( String 

بما أن لغة آدا تدعم المؤشرات السالبة الحقيقية، أي أنها لا تُعطي أي معنى خاص للمؤشرات السالبة، ففي المثال أعلاه، سيقسم المصطلح الفترة من 31 قبل الميلاد إلى 30 ميلادي (لأنه لم يكن هناك عام صفر، فالعام صفر يشير في الواقع إلى 1 قبل الميلاد ).typeHistory_Data_Arrayisarray(-6000..2010)ofHistory_Data; Some_History_Data (-30 .. 30)History_Data

1987: بيرل

إذا كان لدينا

@a = ( 2 , 5 , 7 , 3 , 8 , 6 , 4 );

كما سبق، فإن العناصر الثلاثة الأولى، والعناصر الثلاثة الوسطى، والعناصر الثلاثة الأخيرة ستكون كالتالي:

@a [ 0 .. 2 ]; # (2, 5, 7) @a [ 2 .. 4 ]; # (7, 3, 8) @a [ - 3 ..- 1 ]; # (8, 6, 4)

يدعم بيرل فهارس القوائم السالبة. الفهرس -1 هو العنصر الأخير، و-2 هو العنصر قبل الأخير، وهكذا. بالإضافة إلى ذلك، يدعم بيرل التقطيع بناءً على التعبيرات، على سبيل المثال:

@a [ 3 .. $#a ]; # العنصر الرابع حتى النهاية (3، 8، 6، 4) @a [ grep { ! ( $_ % 3 ) } ( 0 ... $#a ) ]; # العنصر الأول والرابع والسابع (2، 3، 4) @a [ grep { ! (( $_ + 1 ) % 3 ) } ( 0 .. $#a ) ]; # كل عنصر ثالث (7، 6)

بالنسبة للقائمة التالية:

nums : list [ int ] = [ 1 , 3 , 5 , 7 , 8 , 13 , 20 ]

من الممكن تقسيم البيانات باستخدام ترميز مشابه لاسترجاع العناصر:

print ( nums [ 3 ]) # بدون تقطيع # عدد مرات الطباعة: 7 print ( nums [: 3 ]) # من الفهرس 0 (شامل) حتى الفهرس 3 (غير شامل) # عدد مرات الطباعة: [1، 3، 5] print ( nums [ 1 : 5 ]) # عدد مرات الطباعة: [3، 5، 7، 8] print ( nums [ -3 : ]) # عدد مرات الطباعة: [8، 13، 20]

لاحظ أن لغة بايثون تسمح باستخدام فهارس سالبة في القوائم. يُمثل الفهرس -1 العنصر الأخير، و-2 العنصر قبل الأخير، وهكذا. كما تسمح بايثون بخاصية الخطوة بإضافة نقطتين رأسيتين وقيمة. على سبيل المثال:

...

تم تقديم صيغة الخطوة ( nums[1:5:2]) في النصف الثاني من تسعينيات القرن الماضي، نتيجة لطلبات قدمها مستخدمون علميون في مجموعة "matrix-SIG" (مجموعة الاهتمام الخاصة) الخاصة بلغة بايثون. [ 4 ]

قد تختلف دلالات الشرائح باختلاف الكائن؛ ويمكن إدخال دلالات جديدة عند إعادة تعريف عامل الفهرسة. في قوائم بايثون القياسية (وهي مصفوفات ديناميكية )، تُعدّ كل شريحة نسخةً. أما شرائح مصفوفات NumPy ، على النقيض، فهي عبارة عن واجهات عرض لنفس المخزن المؤقت الأساسي.

1992: فورتران 90 وما فوق

في لغة فورتران 90، يتم تحديد الشرائح بالشكل التالي:

الحد الأدنى : الحد الأعلى [: الخطوة ]

كلا الحدين شاملان ويمكن حذفهما، وفي هذه الحالة يتم استخدام حدود المصفوفة المُعلنة افتراضيًا. قيمة الخطوة الافتراضية هي 1. مثال:

حقيقي ، الأبعاد ( م ، ن ) :: أ ! تعريف مصفوفة ، اطبع * ، أ (:، 2 ) ! العمود الثاني ، اطبع * ، أ ( م ، :) ! الصف الأخير ، اطبع * ، أ (: 10 ، : 10 ) ! المصفوفة الفرعية الرئيسية 10×10

يُحدد كل بُعد من أبعاد قيمة المصفوفة في Analytica بواسطة متغير فهرس. عند تقسيم البيانات أو فهرستها، يُحدد بناء الجملة البُعد (أو الأبعاد) التي يتم تقسيمها أو فهرستها بتسمية البُعد. على سبيل المثال:

الفهرس I := 1 .. 5 { تعريف فهرس عددي } الفهرس J := [ 'A' , 'B' , 'C' ] { تعريف فهرس نصي } المتغير X := مصفوفة ( I , J , [[ 10 , 20 , 30 ] , [ 1 , 2 , 3 ] , .... ]) { تعريف قيمة ثنائية الأبعاد } X [ I = 1 , J = 'B' ] -> 20 { فهرس للحصول على قيمة واحدة } X [ I = 1 ] -> مصفوفة ( J , [ 10 , 20 , 30 ]) { استخراج مصفوفة أحادية البعد. } X [ J = 2 ] -> مصفوفة ( I , [ 20 , 2 , .... ]) { استخراج مصفوفة أحادية البعد على البعد الآخر. } X [ I = 1 .. 3 ] {استخرج أول أربعة عناصر من المجموعة I مع جميع العناصر من المجموعة J}

يُشبه تسمية الفهارس في التقطيع والفهرسة تسمية المعاملات في استدعاءات الدوال، بدلاً من الاعتماد على تسلسل ثابت من المعاملات. إحدى مزايا تسمية الفهارس في التقطيع هي أن المبرمج لا يحتاج إلى تذكر تسلسل الفهارس في المصفوفات متعددة الأبعاد. ميزة أخرى أعمق هي أن التعبيرات تُعمم تلقائيًا وبأمان دون الحاجة إلى إعادة كتابتها عند تغير عدد أبعاد المصفوفة X.

تم تقديم خاصية تقسيم المصفوفات في الإصدار 1.0. لم تكن الإصدارات السابقة تدعم هذه الميزة.

لنفترض أن A عبارة عن مصفوفة أحادية البعد مثل

 A = [1:50]; % A = [1, 2, 3, ...49, 50] 

ثم يمكن إنشاء مصفوفة B من أول 5 عناصر من A باستخدام

 B = A[[:4]]; 

وبالمثل، يمكن تعيين B إلى مصفوفة من آخر 5 عناصر من A عبر:

 B = A[[-5:]]; 

ومن الأمثلة الأخرى على التقطيع أحادي البعد ما يلي:

 A[-1] % العنصر الأخير من A A[*] % جميع عناصر A A[[::2]] % جميع العناصر الزوجية من A A[[1::2]] % جميع العناصر الفردية من A A[[-1::-2]] % جميع العناصر الزوجية بترتيب عكسي A[[[0:3], [10:14]]] % العناصر من 0 إلى 3 ومن 10 إلى 14 

يتم تقسيم المصفوفات ذات الأبعاد الأعلى بطريقة مماثلة:

 A[-1, *] % الصف الأخير من A A[[1:5], [2:7]] % مصفوفة ثنائية الأبعاد باستخدام الصفوف من 1 إلى 5 والأعمدة من 2 إلى 7 A[[5:1:-1], [2:7]] % نفس ما سبق باستثناء أن الصفوف معكوسة 

يمكن أن تكون مؤشرات المصفوفات أيضًا مصفوفات من الأعداد الصحيحة. على سبيل المثال، لنفترض أن I = [0:9]لدينا مصفوفة من 10 أعداد صحيحة. عندئذٍ، A[I]تكون مصفوفة العناصر العشرة الأولى من مصفوفة الأعداد الصحيحة مكافئة لها A. ومن الأمثلة العملية على ذلك عملية الفرز مثل:

 I = array_sort(A); % الحصول على قائمة بمؤشرات الفرز B = A[I]; % B هي النسخة المرتبة من A C = A[array_sort(A)]; % نفس ما سبق ولكن بشكل أكثر اختصارًا. 

1999: د

لنفترض وجود المصفوفة التالية:

int [] a = [ 2 , 5 , 7 , 3 , 8 , 6 , 4 , 1 ];

خذ شريحة منه:

int [ ] b = a [ 2..5 ] ;

bوستكون محتويات الشريحة كالتالي [7, 3, 8]. الفهرس الأول للشريحة شامل، والثاني غير شامل.

auto c = a [$ - 4 .. $ - 2 ];

هذا يعني أن المصفوفة الديناميكية cتحتوي الآن على [8, 6]لأن الرمز الموجود داخل [] $يشير إلى طول المصفوفة.

يتم ربط شرائح المصفوفة D بالمصفوفة الأصلية، لذا:

ب [ 2 ] = 10 ؛

يعني ذلك أن aالملف يحتوي الآن على المحتويات [2, 5, 7, 3, 10, 6, 4, 1]. لإنشاء نسخة من بيانات المصفوفة، بدلاً من مجرد اسم مستعار، قم بما يلي:

auto b = a [ 2 .. 5 ]. dup ;

على عكس لغة بايثون، فإن حدود الشرائح في لغة دي لا تصل إلى حد التشبع، لذا فإن الكود المكافئ لكود بايثون هذا يُعد خطأً في لغة دي:

d : list [ int ] = [ 10 , 20 , 30 ] print ( d [ 1 : 5 ]) # يطبع: [20, 30]

تُطبّق لغة البرمجة SuperCollider بعض المفاهيم من لغة J / APL . وتبدو عملية التقطيع كما يلي:

a = [ 3 , 1 , 5 , 7 ] // تعيين مصفوفة للمتغير a a [ 0..1 ] // إرجاع أول عنصرين من a a [.. 1 ] // إرجاع أول عنصرين من a: يمكن حذف الصفر a [ 2 .. ] // إرجاع العناصر من 3 إلى الأخير a [[ 0 , 3 ]] // إرجاع العنصر الأول والرابع من aa [[ 0 , 3 ]] = [ 100 , 200 ] // استبدل العنصرين الأول والرابع من a a [ 2 ..] = [ 100 , 200 ] // استبدل العنصرين الأخيرين من a// إسناد مصفوفة متعددة الأبعاد إلى المتغير a a = [[ 0 , 1 , 2 , 3 , 4 ], [ 5 , 6 , 7 , 8 , 9 ], [ 10 , 11 , 12 , 13 , 14 ], [ 15 , 16 , 17 , 18 , 19 ]]; a . slice ( 2 , 3 ); // أخذ شريحة بإحداثيات 2 و3 (تُرجع 13) a . slice ( nil , 3 ); // أخذ شريحة متعامدة (تُرجع [3, 8, 13, 18])

2005: سمك

تكون المصفوفات في برنامج fish دائمًا ذات أساس واحد، وبالتالي ستبدأ مؤشرات الشريحة الجديدة بالرقم واحد ، بغض النظر عن المؤشرات السابقة.

> set A ( seq 3 2 11 ) # $A عبارة عن مصفوفة تحتوي على القيم 3، 5، 7، 9، 11> echo $A [( seq 2 )] # اطبع أول عنصرين من $A 3 5 > set B $A [ 1 2 ] # تحتوي $B على العنصر الأول والثاني من $A، أي 3 و5> set -e A [ $B ] ; echo $A # امسح العنصرين الثالث والخامس من $A، واطبع $A 3 5 9 

يدعم Cobra أسلوب تقطيع البيانات على غرار بايثون. إذا كان لديك قائمة

الأعداد = [ 1 , 3 , 5 , 7 , 8 , 13 , 20 ]

ثم ستكون العناصر الثلاثة الأولى، والعناصر الثلاثة الوسطى، والعناصر الثلاثة الأخيرة كما يلي:

nums [: 3 ] # يساوي [1، 3، 5] nums [ 2 : 5 ] # يساوي [5، 7، 8] nums [ -3 : ] # يساوي [8، 13، 20]

يدعم برنامج Cobra أيضًا صيغة التقطيع لحلقات "for" الرقمية:

for i in 2 : 5 print i # يطبع 2، 3، 4for j in 3 print j يطبع 0، 1، 2

تعتمد المصفوفات في PowerShell على نظام ترقيم يبدأ من الصفر، ويمكن تعريفها باستخدام عامل الفاصلة:

PS> $a = 2 , 5 , 7 , 3 , 8 , 6 , 4 , 1 PS> # طباعة أول عنصرين من $a: PS> Write-Host -NoNewline $a [ 0 , 1 ] 2 5 PS > # استخراج جزء من المصفوفة باستخدام عامل النطاق: PS> Write-Host -NoNewline $a [ 2..5 ] 7 3 8 6 PS > # استخراج آخر 3 عناصر: PS> Write-Host -NoNewline $a [ -3 ..- 1 ] 6 4 1 PS> # إرجاع محتوى المصفوفة بترتيب عكسي: PS> Write-Host -NoNewline $a [( $ a.Length - 1 ) .. 0 ] # الطول خاصية من System.Object[] 1 4 6 8 3 7 5 2

تدعم لغة Go صيغة مشابهة لصيغة بايثون لتقسيم البيانات (باستثناء الفهارس السالبة). يمكن تقسيم المصفوفات والشرائح. إذا كان لديك شريحة

nums := [] int { 1 , 3 , 5 , 7 , 8 , 13 , 20 }

ثم ستكون العناصر الثلاثة الأولى، والعناصر الثلاثة الوسطى، والعناصر الثلاثة الأخيرة، ونسخة من الشريحة بأكملها كما يلي:

nums [: 3 ] // يساوي []int{1, 3, 5} nums [ 2 : 5 ] // يساوي []int{5, 7, 8} nums [ 4 :] // يساوي []int{8, 13, 20} nums [:] // يساوي []int{1, 3, 5, 7, 8, 13, 20}

تُعتبر الشرائح في لغة Go أنواعًا مرجعية، مما يعني أن الشرائح المختلفة قد تشير إلى نفس المصفوفة الأساسية.

يدعم Cilk Plus صيغة تقسيم المصفوفات كامتداد للغتين C و C++.

array_base [ lower_bound : length [ : stride ]] *

تبدو عملية تقطيع Cilk Plus كما يلي:

A [ : ] // جميع عناصر المتجه A B [ 2 : 6 ] // العناصر من 2 إلى 7 من المتجه B C [ : ][ 5 ] // العمود 5 من المصفوفة C D [ 0 : 3 : 2 ] // العناصر 0، 2، 4 من المتجه D

يختلف تقسيم المصفوفات في Cilk Plus عن تقسيمها في Fortran في جانبين:

  • المعامل الثاني هو الطول (عدد العناصر في الشريحة) بدلاً من الحد الأعلى، وذلك ليكون متسقًا مع مكتبات C القياسية؛
  • لا ينتج عن عملية التقطيع متغير مؤقت، وبالتالي لا تحتاج إلى تخصيص ذاكرة. يجب أن تكون عمليات الإسناد إما غير متداخلة أو متداخلة تمامًا، وإلا ستكون النتيجة غير محددة.

تُشبه عملية تقطيع المصفوفات في لغة جوليا تلك الموجودة في لغة ماتلاب ، ولكنها تستخدم الأقواس المربعة. مثال:

julia> x = rand ( 4 , 3 ) Array 4x3 Array{Float64,2}: 0.323877 0.186253 0.600605 0.404664 0.894781 0.0955007 0.223562 0.18859 0.120011 0.149316 0.779823 0.0690126julia> x [ : , 2 ] # استخراج العمود الثاني. مصفوفة من 4 عناصر {Float64,1}: 0.186253 0.894781 0.18859 0.779823julia> x [ 1 , : ] # الحصول على الصف الأول. مصفوفة 1x3 من النوع Float64، 2: 0.323877 0.186253 0.600605julia> x [ 1 : 2 , 2 : 3 ] # الحصول على المصفوفة الفرعية التي تمتد على الصفوف 1 و2 والأعمدة 2 و3 2x2 Array{Float64,2}: 0.186253 0.600605 0.894781 0.0955007

يدعم Rust تقطيع المصفوفات، والتي تكون من نوع &[T]نوع المصفوفة [T].

let arr : [ i32 ; 9 ] = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]; let slice : & [ i32 ] = & arr [ 2 .. 6 ]; println ( "{:?} " , slice ); // يطبع: [3, 4, 5, 6]

تحتوي لغة C# على طريقتين لتقطيع المصفوفات.

إحدى الطرق هي استخدام الفئة System.ArraySegment. وهناك أيضاً الفئة System.Spanالتي تسمح باستخدام المصفوفات المُخصصة في المكدس أو تقطيع السلاسل النصية.

باستخدام النظام ؛// ... int [] a = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];// باستخدام ArraySegment ArraySegment <int> s1 = new ( a , 2 , 4 ) ; // [3, 4, 5, 6 ]// باستخدام Span Span <int> s2 = a.AsSpan (). Slice ( 2 , 4 ) ; // [ 3, 4, 5, 6 ]

في لغة C++، يمكن إنشاء شريحة مصفوفة باستخدام std::span، مما يسمح بعرض غير مالك للمجموعات أو المصفوفات.

استيراد std ؛باستخدام std :: span ؛ باستخدام std :: vector ؛// ... vector < int > v { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };// يُنشئ نطاقًا باستخدام الفهرس 2، ويأخذ 4 عناصر span < int > s1 ( v + 2 , 4 ); // [3, 4, 5, 6]// يُنشئ نطاقًا على كامل المتجه، ثم يأخذ نطاقًا فرعيًا يبدأ // من الفهرس 2، ويأخذ 4 عناصر span <int> s2 = span <int> ( v , v.size ( ) ). subspan ( 2 , 4 ); // [3, 4, 5 , 6 ]

انظر أيضاً

مراجع

  1. تشانغ، زيمين؛ إيرون، شوتشين (15 مارس 2017). "إكمال الموتر الدقيق باستخدام t-SVD" . معاملات IEEE في معالجة الإشارات . 65 (6). معهد مهندسي الكهرباء والإلكترونيات (IEEE): 1511-1526 . arXiv : 1502.04689 . Bibcode : 2017ITSP...65.1511Z . doi : 10.1109/tsp.2016.2639466 . ISSN 1053-587X . 
  2. 1 2 شركة IBM (1995). مرجع لغة PL/I لنظامي التشغيل MVS و VM .
  3. "تجاوز العشر سنوات" . مجلة MEASURE . هيوليت باكارد. أكتوبر 1976.
  4. ميلمان، ك. جارود؛ أيفازيس، مايكل (2011). "بايثون للعلماء والمهندسين" . الحوسبة في العلوم والهندسة . 13 (2): 9-12 . Bibcode : 2011CSE....13b...9M . doi : 10.1109/MCSE.2011.36 .