আমি কীভাবে একটি তালিকা থেকে নবম উপাদান পেতে পারি?


99

আমি কীভাবে এই সি কোডের সাথে অ্যানালগ, হাস্কেল সূচক অনুসারে একটি তালিকা অ্যাক্সেস করতে পারি?

int a[] = { 34, 45, 56 };
return a[1];

উত্তর:


161

দেখুন এখানে ব্যবহৃত অপারেটর !!

আই [1,2,3]!!1আপনাকে দেয় 2, যেহেতু তালিকাগুলি 0-সূচীযুক্ত।


87
ব্যক্তিগতভাবে আমি বুঝতে পারি না যে এমন কোনও সূচক অ্যাক্সেসর যা একটি মেইন টাইপকে ফিরিয়ে দেয় না তা আইডেমোমেটিক হাস্কেল হিসাবে গ্রহণযোগ্য। [1,2,3]!!6আপনাকে একটি রানটাইম ত্রুটি দেবে। !!টাইপটি থাকলে খুব সহজেই এড়ানো যেত [a] -> Int -> Maybe a। আমাদের হাস্কেল হওয়ার খুব কারণ হ'ল এই ধরনের রানটাইম ত্রুটিগুলি এড়ানো!
ওয়ার্ল্ডসায়িশি

10
এটি একটি বাণিজ্য। প্রতীকটি তারা বেছে নিয়েছে সম্ভবত তারা সবচেয়ে উদ্বেগজনক প্রতীক। সুতরাং আমি মনে করি ধারণাটি এটিকে প্রান্তের ক্ষেত্রে মঞ্জুরি দেওয়ার অনুমতি দিয়েছিল তবে এটিকে অ-প্রতিমূর্তি হিসাবে দেখাতে সক্ষম করে।
সিডোসবার

4
itemOf :: Int -> [a] -> Maybe a; x `itemOf` xs = let xslen = length xs in if ((abs x) > xslen) then Nothing else Just (xs !! (x `mod` xslen))। দ্রষ্টব্য, এটি অসীম তালিকায় বিপর্যয়করভাবে ব্যর্থ হবে।
djvs

4
!!এটি একটি আংশিক এবং এইভাবে অনিরাপদ ফাংশন। নিচে এবং ব্যবহার মন্তব্য কটাক্ষপাত lens stackoverflow.com/a/23627631/2574719
goetzc

90

আমি বলছি না যে আপনার প্রশ্ন বা প্রদত্ত উত্তরের সাথে কিছু ভুল আছে, তবে আপনি ভবিষ্যতে নিজের সময় বাঁচানোর জন্য এই গুগল যে দুর্দান্ত সরঞ্জামটি সম্পর্কে জানতে চান তা : Hoogle এর সাহায্যে আপনি স্ট্যান্ডার্ড লাইব্রেরি ফাংশন সন্ধান করতে পারেন এটি একটি প্রদত্ত স্বাক্ষরের সাথে মেলে। সুতরাং, সম্পর্কে কিছু না জেনে !!, আপনার ক্ষেত্রে আপনি "এমন কিছু অনুসন্ধান করতে পারেন যা তরলাকারীদের Intএকটি তালিকা নেয় এবং একটি কিছু প্রদান করে", যথা

Int -> [a] -> a

লো এবং দেখুন , !!প্রথম ফলাফল হিসাবে (যদিও টাইপ স্বাক্ষরটি আসলে আমরা অনুসন্ধান করেছি তার তুলনায় বিপরীতে দুটি যুক্তি রয়েছে)। ঝরঝরে, হাহ?

এছাড়াও, যদি আপনার কোড সূচকের উপর নির্ভর করে (তালিকার সামনে থেকে গ্রাস না করে), তালিকাগুলি আসলে সঠিক ডেটা কাঠামো নাও হতে পারে। ও (1) সূচক-ভিত্তিক অ্যাক্সেসের জন্য আরও দক্ষ বিকল্প রয়েছে যেমন অ্যারে বা ভেক্টর


4
Hoogle একেবারে দুর্দান্ত। প্রতিটি হাস্কেল প্রোগ্রামার এটি জানা উচিত। হায়ু ( holumbus.fh-welel.de/hayoo/hayoo.html ) নামে একটি বিকল্প রয়েছে । এটি আপনার টাইপ করার সাথে সাথে অনুসন্ধান করে তবে এটি Hoogle এর মতো চালাক বলে মনে হয় না।
musiKk

61

ব্যবহারের বিকল্প (!!)হ'ল লেন্স প্যাকেজ এবং এর elementফাংশন এবং সম্পর্কিত অপারেটরগুলি ব্যবহার করা। লেন্স উপরে এবং তালিকা পরলোক কাঠামো ও নেস্টেড স্ট্রাকচার বিভিন্ন ধরণের ব্যবহার করার জন্য একটি অভিন্ন ইন্টারফেস প্রদান করে। নীচে আমি উদাহরণ সরবরাহে মনোনিবেশ করব এবং প্রকার স্বাক্ষর এবং লেন্স প্যাকেজের পিছনে তত্ত্ব উভয়কেই গ্লোস করব will আপনি তত্ত্ব সম্পর্কে আরো জানতে চান একটি ভাল জায়গা শুরু করার জন্য এ রিডমি ফাইল GitHub রেপো

তালিকা এবং অন্যান্য ডেটাটাইপ অ্যাক্সেস করা

লেন্স প্যাকেজে অ্যাক্সেস পাওয়া যাচ্ছে

কমান্ড লাইনে:

$ cabal install lens
$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
> import Control.Lens


অ্যাক্সেস তালিকাগুলি

ইনফিক্স অপারেটরের সাথে একটি তালিকা অ্যাক্সেস করতে

> [1,2,3,4,5] ^? element 2  -- 0 based indexing
Just 3

(!!)সীমার বাইরে কোনও উপাদান অ্যাক্সেস করার সময় এটির বিপরীতে কোনও ব্যতিক্রম হবে না এবং এর Nothingপরিবর্তে ফিরে আসবে । এটি প্রায়শই আংশিক ফাংশন এড়ানোর পরামর্শ দেওয়া হয় (!!)বা headযেহেতু তাদের আরও কোণার কেস থাকে এবং রান টাইম ত্রুটি হওয়ার সম্ভাবনা বেশি থাকে। এই উইকি পৃষ্ঠায় আংশিক কার্যকারিতা এড়ানোর জন্য আপনি আরও কিছুটা পড়তে পারেন ।

> [1,2,3] !! 9
*** Exception: Prelude.(!!): index too large

> [1,2,3] ^? element 9
Nothing

আপনি লেন্স কৌশলটি আংশিক ফাংশন হিসাবে বাধ্য করতে পারেন এবং (^?!)অপারেটরের পরিবর্তে অপারেটরটি ব্যবহার করে সীমা ছাড়িয়ে গেলে একটি ব্যতিক্রম ছুঁড়ে ফেলতে পারেন (^?)

> [1,2,3] ^?! element 1
2
> [1,2,3] ^?! element 9
*** Exception: (^?!): empty Fold


তালিকাগুলি ব্যতীত অন্যান্য ধরণের সাথে কাজ করা

এটি কেবল তালিকার মধ্যে সীমাবদ্ধ নয়। উদাহরণস্বরূপ, একই কৌশলটি স্ট্যান্ডার্ড পাত্রে প্যাকেজ থেকে গাছগুলিতে কাজ করে ।

 > import Data.Tree
 > :{
 let
  tree = Node 1 [
       Node 2 [Node 4[], Node 5 []]
     , Node 3 [Node 6 [], Node 7 []]
     ]
 :}
> putStrLn . drawTree . fmap show $tree
1
|
+- 2
|  |
|  +- 4
|  |
|  `- 5
|
`- 3
   |
   +- 6
   |
   `- 7

আমরা এখন গভীরতার প্রথম ক্রমে গাছের উপাদানগুলি অ্যাক্সেস করতে পারি:

> tree ^? element 0
Just 1
> tree ^? element 1
Just 2
> tree ^? element 2
Just 4
> tree ^? element 3
Just 5
> tree ^? element 4
Just 3
> tree ^? element 5
Just 6
> tree ^? element 6
Just 7

আমরা পাত্রে প্যাকেজ থেকে ক্রমগুলি অ্যাক্সেস করতে পারি :

> import qualified Data.Sequence as Seq
> Seq.fromList [1,2,3,4] ^? element 3
Just 4

আমরা ভেক্টর প্যাকেজ থেকে স্ট্যান্ডার্ড ইন ইনডেক্সড অ্যারে , স্ট্যান্ডার্ড টেক্সট প্যাকেজ থেকে পাঠ্য , বাইটস্ট্রিংগুলি স্ট্যান্ডার্ড বাইট্রেস্টিং প্যাকেজ এবং অন্যান্য অনেকগুলি স্ট্যান্ডার্ড ডেটা স্ট্রাকচার অ্যাক্সেস করতে পারি । অ্যাক্সেসের এই স্ট্যান্ডার্ড পদ্ধতিটি আপনার ব্যক্তিগত ডেটা স্ট্রাকচারগুলিতে টাইপক্লাস ট্যারেবলযোগ্য উদাহরণ হিসাবে তৈরি করা যেতে পারে , লেন্স ডকুমেন্টেশনে ট্র্যাভারেবলের দীর্ঘতর উদাহরণ দেখুন


নেস্টেড স্ট্রাকচার

নেস্টেড কাঠামোর মধ্যে নিচে খনন লেন্স সঙ্গে সহজ hackage । উদাহরণস্বরূপ তালিকার তালিকায় একটি উপাদান অ্যাক্সেস করা:

> [[1,2,3],[4,5,6]] ^? element 0 . element 1
Just 2
> [[1,2,3],[4,5,6]] ^? element 1 . element 2
Just 6

নেস্টেড ডেটা স্ট্রাকচার বিভিন্ন ধরণের থাকলেও এই রচনাটি কাজ করে। সুতরাং উদাহরণস্বরূপ যদি আমার কাছে গাছগুলির একটি তালিকা থাকে:

> :{
 let
  tree = Node 1 [
       Node 2 []
     , Node 3 []
     ]
 :}
> putStrLn . drawTree . fmap show $ tree
1
|
+- 2
|
`- 3
> :{
 let 
  listOfTrees = [ tree
      , fmap (*2) tree -- All tree elements times 2
      , fmap (*3) tree -- All tree elements times 3
      ]            
 :}

> listOfTrees ^? element 1 . element 0
Just 2
> listOfTrees ^? element 1 . element 1
Just 4

যতক্ষণ না তারা Traversableপ্রয়োজনীয়তা পূরণ করে স্বেচ্ছাচারিতামূলক প্রকারের সাথে আপনি গভীরভাবে বাসা বাঁধতে পারেন । সুতরাং পাঠ্যের ক্রমগুলির গাছগুলির একটি তালিকা অ্যাক্সেস করা কোনও ঘাম নয়।


নবম উপাদান পরিবর্তন করা হচ্ছে

অনেক ভাষায় একটি সাধারণ ক্রিয়াকলাপ হ'ল একটি অ্যারেতে সূচিযুক্ত অবস্থান নির্ধারণ করা। অজগর আপনি সম্ভবত:

>>> a = [1,2,3,4,5]
>>> a[3] = 9
>>> a
[1, 2, 3, 9, 5]

লেন্স প্যাকেজের সাথে এই কার্যকারিতা দেয় (.~)অপারেটর। যদিও অজগর থেকে পৃথক মূল তালিকাটি পরিবর্তিত হয় না, বরং একটি নতুন তালিকা ফিরে আসে।

> let a = [1,2,3,4,5]
> a & element 3 .~ 9
[1,2,3,9,5]
> a
[1,2,3,4,5]

element 3 .~ 9কেবল একটি ফাংশন এবং (&)অপারেটর, লেন্স প্যাকেজের অংশ , কেবল বিপরীত ফাংশন অ্যাপ্লিকেশন। এখানে এটি আরও সাধারণ ফাংশন অ্যাপ্লিকেশন সহ।

> (element 3 .~ 9) [1,2,3,4,5]
[1,2,3,9,5]

নির্ধারিত কাজগুলি পুনরায় নির্বিচারে বাসা বাঁধার সাথে পুরোপুরি সূক্ষ্মভাবে কাজ করে Traversable

> [[1,2,3],[4,5,6]] & element 0 . element 1 .~ 9
[[1,9,3],[4,5,6]]

4
আমি Data.Traversableকি পুনরায় রফতানির চেয়ে লিঙ্ক যুক্ত করতে পারি lens?
dfeuer

@ ডিফিউয়ার - আমি ডেটাতে একটি লিঙ্ক যুক্ত করেছি base বেসে ট্র্যাভারেবল। আমিও পুরানো লিঙ্কটি রেখেছি এবং উল্লেখ করেছি যে লেন্স ডকুমেন্টেশনে ট্র্যাভেলারদের উদাহরণের একটি দীর্ঘ তালিকা রয়েছে। পরামর্শের জন্য ধন্যবাদ.
দাভোরাক

11

সরাসরি উত্তর ইতিমধ্যে দেওয়া হয়েছিল: ব্যবহার করুন !!

তবে newbies প্রায়শই এই অপারেটরকে অতিরিক্ত ব্যবহার করার প্রবণতা দেখায় যা হাস্কেলের জন্য ব্যয়বহুল (কারণ আপনি একক লিঙ্কযুক্ত তালিকায় কাজ করেন, অ্যারেগুলিতে নয়)। এটি এড়াতে বেশ কয়েকটি দরকারী কৌশল রয়েছে, সবচেয়ে সহজতমটি জিপটি ব্যবহার করে। আপনি যদি লিখেন তবে আপনি zip ["foo","bar","baz"] [0..]প্রতিটি জোড়ের প্রতিটি উপাদানের সাথে সূচকগুলি "সংযুক্ত" সহ একটি নতুন তালিকা পাবেন: [("foo",0),("bar",1),("baz",2)]যা প্রায়শই আপনার প্রয়োজন মতো হয়।


4
সেখানে আপনার ধরণের বিষয়ে আপনারও যত্নবান হওয়া দরকার। বেশিরভাগ সময় আপনি সূচকগুলি দ্রুত মেশিন ইন্টের চেয়ে ধীর ইন্টিজার হয়ে শেষ করতে চান না। আপনার ফাংশনটি ঠিক কী করে এবং আপনার টাইপিংটি কতটা স্পষ্ট তার উপর নির্ভর করে, হ্যাস্কেল [ইনট] এর পরিবর্তে [0 ..] টাইপ [পূর্ণসংখ্যা] হতে পারে।
chrisdb

4

আপনি ব্যবহার করতে পারেন !!, তবে আপনি যদি এটি পুনরাবৃত্তভাবে করতে চান তবে নীচে এটি করার একটি উপায় রয়েছে:

dataAt :: Int -> [a] -> a
dataAt _ [] = error "Empty List!"
dataAt y (x:xs)  | y <= 0 = x
                 | otherwise = dataAt (y-1) xs

4

হাস্কেলের স্ট্যান্ডার্ড তালিকার ডেটা টাইপ forall t. [t]বাস্তবায়নের ক্ষেত্রে সি লিঙ্কিত তালিকার সাথে সাদৃশ্যপূর্ণ এবং এর প্রয়োজনীয় বৈশিষ্ট্যগুলি ভাগ করে। লিঙ্কযুক্ত তালিকাগুলি অ্যারে থেকে খুব আলাদা। সর্বাধিক উল্লেখযোগ্যভাবে, সূচকের মাধ্যমে অ্যাক্সেস হ'ল একটি ও (1) লিনিয়ার-, ও (1) ধ্রুবক-সময় অপারেশনের পরিবর্তে।

আপনার যদি ঘন ঘন এলোমেলো অ্যাক্সেসের প্রয়োজন হয় তবে Data.Arrayমানটি বিবেচনা করুন ।

!!সীমার বাইরে সূচকগুলির জন্য ক্র্যাশকে উস্কে দেওয়া একটি অনিরাপদ আংশিক সংজ্ঞায়িত ফাংশন। জেনে রাখুন যে মান গ্রন্থাগার কিছু যেমন আংশিক ফাংশন (ধারণ করা head, lastইত্যাদি)। সুরক্ষার জন্য, একটি বিকল্প ধরণ Maybeবা Safeমডিউল ব্যবহার করুন।

যুক্তিসঙ্গতভাবে দক্ষ, শক্তসমর্থ মোট (সূচকগুলির জন্য ≥ 0) সূচীকরণ কার্যের উদাহরণ:

data Maybe a = Nothing | Just a

lookup :: Int -> [a] -> Maybe a
lookup _ []       = Nothing
lookup 0 (x : _)  = Just x
lookup i (_ : xs) = lookup (i - 1) xs

লিঙ্কযুক্ত তালিকার সাথে কাজ করা, প্রায়শই অর্ডিনালগুলি সুবিধাজনক:

nth :: Int -> [a] -> Maybe a
nth _ []       = Nothing
nth 1 (x : _)  = Just x
nth n (_ : xs) = nth (n - 1) xs

এই ক্রিয়াকলাপগুলি যথাক্রমে নেতিবাচক এবং অ-অসম্পূর্ণ ইনটসের জন্য চিরতরে পুনরাবৃত্তি করে।
বজরতুর থরল্যাকিয়াস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.