আমি কীভাবে একটি ইউআরএল সংক্ষিপ্ত তৈরি করব?


667

আমি একটি ইউআরএল সংক্ষিপ্ততর পরিষেবা তৈরি করতে চাই যেখানে আপনি একটি ইনপুট ক্ষেত্রে দীর্ঘ URL লিখতে পারেন এবং পরিষেবাটি " http://www.example.org/abcdef" এর URL টি সংক্ষিপ্ত করে তোলে ।

" abcdef" এর পরিবর্তে ছয়টি অক্ষর সমন্বিত অন্য কোনও স্ট্রিং থাকতে পারে a-z, A-Z and 0-9। এটি 56 ~ 57 বিলিয়ন সম্ভাব্য স্ট্রিংগুলি তৈরি করে।

আমার পদ্ধতি:

আমার কাছে তিনটি কলাম সহ একটি ডাটাবেস টেবিল রয়েছে:

  1. আইডি, পূর্ণসংখ্যা, স্বতঃবৃদ্ধি
  2. দীর্ঘ, স্ট্রিং, দীর্ঘ ইউআরএল ব্যবহারকারী প্রবেশ করেছে entered
  3. সংক্ষিপ্ত, স্ট্রিং, সংক্ষিপ্ত ইউআরএল (বা মাত্র ছয় অক্ষর)

আমি তখন লম্বা ইউআরএলটি টেবিলের মধ্যে sertোকাতাম। তারপরে আমি " id" এর জন্য অটো-ইনক্রিমেন্ট মান নির্বাচন করব এবং এর একটি হ্যাশ তৈরি করব। এই হ্যাশটি " short" হিসাবে sertedোকানো উচিত । তবে আমি কী ধরণের হ্যাশ তৈরি করব? এমডি 5 এর মতো হ্যাশ অ্যালগরিদমগুলি খুব দীর্ঘ স্ট্রিং তৈরি করে। আমি মনে করি এই অ্যালগরিদমগুলি আমি ব্যবহার করি না। একটি স্ব-নির্মিত অ্যালগরিদমও কাজ করবে।

আমার ধারণা:

" http://www.google.de/" এর জন্য আমি অটো-ইনক্রিমেন্ট আইডি পাই 239472। তারপরে আমি নিম্নলিখিত পদক্ষেপগুলি করি:

short = '';
if divisible by 2, add "a"+the result to short
if divisible by 3, add "b"+the result to short
... until I have divisors for a-z and A-Z.

সংখ্যাটি আর বিভাজ্য না হওয়া পর্যন্ত এটি পুনরাবৃত্তি হতে পারে। আপনি কি মনে করেন এটি একটি ভাল পদ্ধতির? আপনি একটি ভাল ধারণা আছে?

এই বিষয়ে চলমান আগ্রহের কারণে, আমি জাভাস্ক্রিপ্ট , পিএইচপি , পাইথন এবং জাভা বাস্তবায়ন সহ গিটহাবের একটি কার্যকর সমাধান প্রকাশ করেছি । আপনি চাইলে আপনার সমাধান যুক্ত করুন :)


5
@ গুড এই ফাংশনগুলির মূল বিষয়টি হ'ল তাদের একটি বিপরীত কার্য রয়েছে। এর অর্থ আপনার উভয় encode()এবং decode()ফাংশন থাকতে পারে। ধাপ তাই হয়: (1) সংরক্ষণ করুন URL টি ডাটাবেসের মধ্যে (2) সঙ্গে সংক্ষিপ্ত স্ট্রিং ডাটাবেসের (3) রূপান্তর পূর্ণসংখ্যা আইডি থেকে যে URL জন্য অনন্য সারি আইডি পান encode(), যেমন 273984করতে f5a4(4) সংক্ষিপ্ত স্ট্রিং (যেমন ব্যবহার করুন f4a4) আপনার শেরেবল ইউআরএল (৫) একটি সংক্ষিপ্ত স্ট্রিংয়ের জন্য অনুরোধ পাওয়ার সময় (যেমন 20a8), স্ট্রিংটি একটি পূর্ণসংখ্যার আইডিতে ডিকোড করুন decode()()) প্রদত্ত আইডির জন্য ডাটাবেসে ইউআরএল সন্ধান করুন। রূপান্তরের জন্য, ব্যবহার: github.com/delight-im/ShortURL
কাকের ডাক

@ মারকো, হ্যাশটি ডাটাবেসে সংরক্ষণ করার বিষয়টি কী?
মাকসিম ভি।

3
@MaksimVi। আপনার যদি একটি বিবর্তনযোগ্য ফাংশন থাকে তবে কিছুই নেই। যদি আপনার একমুখী হ্যাশ ফাংশন থাকে তবে একটি হবে।
কাও

1
যদি আমরা একটি URL সংক্ষিপ্ত করতে সহজ সিআরসি 32 এলগরিদম ব্যবহার করি তবে কী ভুল হবে? যদিও কোনও সংঘর্ষের খুব কম সম্ভাবনা রয়েছে (একটি সিআরসি 32 আউটপুট সাধারণত 8 টি অক্ষরের দীর্ঘ হয় এবং এটি আমাদের 30 মিলিয়নেরও বেশি সম্ভাবনা দেয়) যদি উত্পন্ন সিআরসি 32 আউটপুটটি ইতিমধ্যে ব্যবহৃত হয়ে থাকে এবং ডাটাবেসে পাওয়া যায় তবে আমরা লম্বা ইউআরএলটিকে একটি এলোমেলো সংখ্যার সাথে লবণ দিতে পারি could যতক্ষণ না আমরা একটি সিআরসি 32 আউটপুট খুঁজে পাই যা আমার ডাটাবেসে অনন্য। এটি সাধারণ সমাধানের জন্য কতটা খারাপ বা ভিন্ন বা কুরুচিপূর্ণ হবে?
রাকিব

উত্তর:


816

আমি আপনার "সংখ্যাকে স্ট্রিংয়ে রূপান্তর করুন" পদ্ধতির চালিয়ে যাব। তবে, আপনি বুঝতে পারবেন যে আপনার প্রস্তাবিত অ্যালগরিদম ব্যর্থ হয় যদি আপনার আইডি প্রাইম এবং 52 এরও বেশি হয়

তাত্ত্বিক প্রেক্ষাপট

আপনি একটি প্রয়োজন Bijective ফাংশন । এটি প্রয়োজনীয় যাতে আপনার চ (123) = 'অ্যাবসি' ফাংশনের জন্য আপনি একটি বিপরীতমুখী ফাংশন g ('abc') = 123 খুঁজে পেতে পারেন । এর অর্থ:

  • অবশ্যই কোনও x1, x2 (x1 ≠ x2 সহ) থাকতে হবে যা f (x1) = f (x2) তৈরি করবে ,
  • এবং প্রতি y এর জন্য আপনাকে অবশ্যই একটি x খুঁজে পেতে সক্ষম করতে হবে যাতে f (x) = y

সংক্ষিপ্ত URL এ কীভাবে আইডি রূপান্তর করবেন

  1. আমরা যে অক্ষরটি ব্যবহার করতে চাই তার কথা ভাবুন। আপনার ক্ষেত্রে, এটি [a-zA-Z0-9]। এটি 62 অক্ষর রয়েছে ।
  2. একটি স্বয়ং-উত্পন্ন, অনন্য সংখ্যাসূচক কী নিন ( idউদাহরণস্বরূপ কোনও মাইএসকিউএল টেবিলের স্ব-বর্ধিত )।

    এই উদাহরণস্বরূপ, আমি 125 10 ( 10 এর বেস সহ 125) ব্যবহার করব।

  3. এখন আপনাকে 125 10 কে এক্স 62 (বেস 62) এ রূপান্তর করতে হবে ।

    125 10 = 2 × 62 1 + 1 × 62 0 =[2,1]

    এর জন্য পূর্ণসংখ্যা বিভাগ এবং মডুলোর ব্যবহার প্রয়োজন। একটি সিউডো কোড উদাহরণ:

    digits = []
    
    while num > 0
      remainder = modulo(num, 62)
      digits.push(remainder)
      num = divide(num, 62)
    
    digits = digits.reverse
    

    এখন মানচিত্র আপনার বর্ণমালায় সূচকগুলি 2 এবং 1 তে । আপনার ম্যাপিংটি (উদাহরণস্বরূপ একটি অ্যারে সহ) এটি দেখতে কেমন হতে পারে:

    0  → a
    1  → b
    ...
    25 → z
    ...
    52 → 0
    61 → 9
    

    2 → সি এবং 1 → বি দিয়ে আপনি সিবি 62 পাবেন সংক্ষিপ্ত URL হিসাবে ।

    http://shor.ty/cb
    

প্রাথমিক আইডিতে একটি সংক্ষিপ্ত URL কীভাবে সমাধান করবেন

বিপরীতে আরও সহজ। আপনি কেবল আপনার বর্ণমালায় একটি বিপরীত অনুসন্ধান করেন।

  1. e9a 62 "বর্ণমালায় চতুর্থ, 61 তম এবং 0 র্থ " সমাধান করা হবে।

    e9a 62 = [4,61,0]= 4 × 62 2 + 61 × 62 1 + 0 × 62 0 = 19158 10

  2. এখন আপনার ডাটাবেস-রেকর্ডটি সন্ধান করুন WHERE id = 19158 করুন এবং পুনঃনির্দেশ করুন।

বাস্তবায়ন উদাহরণ (মন্তব্যকারীদের দ্বারা সরবরাহিত)


18
দূষিত জাভাস্ক্রিপ্ট কোডের জন্য ইউআরএল স্যানিটাইজ করতে ভুলবেন না! মনে রাখবেন যে জাভাস্ক্রিপ্ট করুন Base64- একটি URL তাই ঠিক 'জাভাস্ক্রিপ্ট' এর জন্য অনুসন্ধানের মধ্যে এনকোড করা যেতে পারে ভাল enough.j নয়
বিয়ন্সের

3
বিপরীতমুখী হবার জন্য একটি ক্রিয়াকলাপ অবশ্যই দ্বিপদী (ইনজেকটিভ এবং সার্জেক্টিভ) হতে হবে।
গম্বো

57
চিন্তার জন্য খাদ্য, এটি ইউআরএলে দুটি চরিত্রের চেকসাম যুক্ত করা কার্যকর হতে পারে। এটি আপনার সিস্টেমে সমস্ত url- এর সরাসরি পুনরাবৃত্তি রোধ করবে। কিছু সাধারণ কিছু যেমন (চেকসাম (আইডি)% (62) 2)) + চ (আইডি) = url_id
কোবলাস

6
ইউআরএলগুলিকে স্যানিটাইজ করার যতটা সমস্যা রয়েছে তার মধ্যে একটি হ'ল স্প্যাম ফিল্টারগুলি এড়ানোর জন্য স্প্যামাররা তাদের পরিষেবাগুলি ইউআরএলকে মাস্ক করার জন্য ব্যবহার করছে। আপনি হয় পরিচিত ভাল অভিনেতাদের পরিষেবা সীমাবদ্ধ করতে হবে, বা দীর্ঘ url- এ স্প্যাম ফিল্টারিং প্রয়োগ করতে হবে। অন্যথায় আপনি স্প্যামার দ্বারা আপত্তিজনক হবে।
এডওয়ার্ড ফ্যাল্ক

74
বেস 62 একটি খারাপ পছন্দ হতে পারে কারণ এতে চ * শব্দ উত্পন্ন করার সম্ভাবনা রয়েছে (উদাহরণস্বরূপ, 3792586=='F_ck'_ এর জায়গায় ইউ সহ)। এটি হ্রাস করার জন্য আমি ইউ / ইউ এর মতো কয়েকটি অক্ষর বাদ দেব।
পাওলো স্কার্ডাইন

56

আপনি কেন একটি হ্যাশ ব্যবহার করতে চান?

আপনি কেবলমাত্র নিজের অটো-বর্ধিত মানের একটি বর্ণানুক্রমিক মানটির একটি সহজ অনুবাদ ব্যবহার করতে পারেন। কিছু বেস রূপান্তর ব্যবহার করে আপনি এটি সহজেই করতে পারেন। বলুন আপনার অক্ষরের স্থান (AZ, az, 0-9, ইত্যাদি) 40 টি অক্ষর রয়েছে, আইডিটিকে একটি বেস -40 সংখ্যায় রূপান্তর করুন এবং অক্ষর হিসাবে অঙ্কগুলি ব্যবহার করুন।


13
এজেড, এজেড এবং 0-9 = 62 অক্ষর, 40 নয়, আপনি সঠিক অবস্থানে রয়েছেন from
ইভান তেরান

ধন্যবাদ! আমার তখন বেস -২২ বর্ণমালাটি ব্যবহার করা উচিত? en.wikedia.org/wiki/Base_62 তবে আমি কীভাবে আইডিএসকে বেস -২২ সংখ্যায় রূপান্তর করতে পারি?
কাও

- একটি বেস রূপান্তর অ্যালগরিদম অবশ্যই শুনব ব্যবহার en.wikipedia.org/wiki/Base_conversion#Change_of_radix
shoosh

2
"আপনি কেন একটি হ্যাশ ব্যবহার করতে চান?" সম্পর্কিত, স্বতঃবৃদ্ধির উপর ভিত্তি করে একটি বেস রূপান্তরটি অনুক্রমিক ইউআরএল তৈরি করতে চলেছে, সুতরাং আপনার লোকেরা অন্যান্য লোকের সংক্ষিপ্ত URL গুলি "ব্রাউজ" করতে সক্ষম হতে স্বাচ্ছন্দ্য বোধ করবে, ঠিক আছে?
অ্যান্ড্রু কোলসন

2
পর্যাপ্ত সংস্থান এবং সময় দিয়ে আপনি যে কোনও URL সংক্ষিপ্তকরণ পরিষেবার সমস্ত URL টি "ব্রাউজ" করতে পারেন।
21

51
public class UrlShortener {
    private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    private static final int    BASE     = ALPHABET.length();

    public static String encode(int num) {
        StringBuilder sb = new StringBuilder();
        while ( num > 0 ) {
            sb.append( ALPHABET.charAt( num % BASE ) );
            num /= BASE;
        }
        return sb.reverse().toString();   
    }

    public static int decode(String str) {
        int num = 0;
        for ( int i = 0; i < str.length(); i++ )
            num = num * BASE + ALPHABET.indexOf(str.charAt(i));
        return num;
    }   
}

আমি সত্যিই ধারণাটি পছন্দ করি, এটির সাথে আমার একটাই সমস্যাটি হ'ল আমি ডিকোড ফাংশনে সীমাবদ্ধতার বাইরেও সংখ্যা পরিবর্তনশীল রাখি (এমনকি দীর্ঘকাল ধরে), কীভাবে এটি কার্যকর করবেন আপনার কোনও ধারণা আছে? নাকি এটি কেবল তাত্ত্বিক?
ব্যবহারকারী 1322801

@ ব্যবহারকারী 1322801: সম্ভবত আপনি এমন কিছু ডিকোড করার চেষ্টা করছেন যা এনকোড ফাংশনটি আসলে পরিচালনা করতে পারে তার থেকে অনেক বড়। আপনি যদি "ইনটস" এর সমস্তটিকে বিগইন্টিজায়ারে রূপান্তর করেন তবে আপনি এর থেকে আরও কিছু মাইলেজ পেতে পারেন তবে আপনি যদি> 9223372036854775807 সূচক না পান তবে সম্ভবত দীর্ঘই হওয়া উচিত।
biggusjimmus

2
আমি কি জানতে পারি যে বিপরীতের গুরুত্ব কী? যেমন sb.revers ()। toString ();
ডটনেট ডিকোডার

এটি 62 ^ 62 = 1.7 ট্রিলিয়ন?
নোহ টনি

33

আপনার প্রশ্নের উত্তর নয়, তবে আমি কেস-সংবেদনশীল সংক্ষিপ্ত URL গুলি ব্যবহার করব না। এগুলি মনে রাখা শক্ত, সাধারণত অপঠনযোগ্য (অনেকগুলি ফন্ট 1 এবং l, 0 এবং O এবং অন্যান্য অক্ষরগুলি খুব একইরূপে উপস্থাপন করে যে তারা পার্থক্যটি বলা অসম্ভবের কাছাকাছি) এবং ডান দিকের ত্রুটিযুক্ত প্রবণ। শুধুমাত্র নিম্ন বা উচ্চতর ক্ষেত্রে ব্যবহার করার চেষ্টা করুন।

এছাড়াও, এমন কোনও ফর্ম্যাট রাখার চেষ্টা করুন যেখানে আপনি সংখ্যার সাথে অক্ষরগুলি পূর্বনির্ধারিত আকারে মিশ্রিত করুন। এমন অধ্যয়ন রয়েছে যা দেখায় যে লোকেরা একটি ফর্ম অন্যের চেয়ে ভাল মনে রাখে ( নাম-চর-চর-নাম্বার-চর-চর এর মতো কিছু চেষ্টা করুন Try আমি জানি এটি কম্বিনেশনগুলি কমিয়ে দেবে, বিশেষত আপনার যদি উচ্চ এবং নিম্নতর কেস না থাকে তবে এটি আরও ব্যবহারযোগ্য এবং তাই দরকারী।


2
আপনাকে ধন্যবাদ, খুব ভাল ধারণা। আমি এখনও এটি সম্পর্কে চিন্তা করিনি। এটি স্পষ্ট যে এটি কীভাবে ব্যবহার করে তা বোঝায় কি না তা নির্ভর করে।
কাও

19
লোকেরা যদি সংক্ষিপ্ত ইউআরএলগুলি কঠোরভাবে অনুলিপি করে এবং পেস্ট করে তবে এটি কোনও সমস্যা হবে না।
এডওয়ার্ড ফালক

2
সংক্ষিপ্ত url এর উদ্দেশ্যটি স্মরণীয় বা কথা বলা সহজ নয়। শুধুমাত্র ক্লিক বা অনুলিপি / পেস্ট করুন।
হুগো নোগুয়েরা

হ্যাঁ আমি ভেবেছিলাম সংক্ষিপ্ত ইউআরএল কেবল লোকেরা এটির তালিকা তৈরি বা ইমেল করতে পারে এবং তাই এটি সংক্ষিপ্ত এবং 200 টির মতো ইউআরএল এর মতো অক্ষর গ্রহণ করবে না, সুতরাং কেস কোনও সমস্যা নয়
টির অবিচ্ছিন্নতা

29

আমার পদ্ধতির: ডেটাবেস আইডি নিন, তারপরে বেস 36 এটিকে এনকোড করুন । আমি উপরের এবং ছোট হাতের অক্ষর উভয়ই ব্যবহার করবো না, কারণ টেলিফোনে সেই ইউআরএলগুলি একটি দুঃস্বপ্ন দেখায়, তবে আপনি অবশ্যই সহজেই ফাংশনটি বেস 62 এন / ডিকোডার হিসাবে প্রসারিত করতে পারেন।


ধন্যবাদ, আপনি ঠিক বলেছেন। আপনার যদি 2,176,782,336 সম্ভাবনা থাকে বা 56,800,235,584, তা সমান: উভয়ই যথেষ্ট। সুতরাং আমি বেস 36 এনকোডিং ব্যবহার করব।
কাও

এটি সুস্পষ্ট হতে পারে তবে পিএইচপি টনিমারস্টন.নেট
রায়ান হোয়াইট

8

এখানে আমার পিএইচপি 5 ক্লাস।

<?php
class Bijective
{
    public $dictionary = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    public function __construct()
    {
        $this->dictionary = str_split($this->dictionary);
    }

    public function encode($i)
    {
        if ($i == 0)
        return $this->dictionary[0];

        $result = '';
        $base = count($this->dictionary);

        while ($i > 0)
        {
            $result[] = $this->dictionary[($i % $base)];
            $i = floor($i / $base);
        }

        $result = array_reverse($result);

        return join("", $result);
    }

    public function decode($input)
    {
        $i = 0;
        $base = count($this->dictionary);

        $input = str_split($input);

        foreach($input as $char)
        {
            $pos = array_search($char, $this->dictionary);

            $i = $i * $base + $pos;
        }

        return $i;
    }
}

6

একটি নোড.জেএস এবং মঙ্গোডিবি সমাধান

যেহেতু আমরা মঙ্গোডিবি 12 বাইট সহ একটি নতুন অবজেক্টআইডি তৈরি করতে ব্যবহার করে সেই ফর্ম্যাটটি আমরা জানি।

  • ইউনিক্স পর্বের সময় থেকে সেকেন্ডের প্রতিনিধিত্বকারী একটি 4-বাইট মান,
  • একটি 3 বাইট মেশিন শনাক্তকারী,
  • একটি 2 বাইট প্রক্রিয়া আইডি
  • একটি এলোমেলো মান দিয়ে শুরু করে একটি 3 বাইট কাউন্টার (আপনার মেশিনে)।

উদাহরণ (আমি একটি এলোমেলো ক্রম চয়ন করি) a1b2c3d4e5f6g7h8i9j1k2l3

  • a1b2c3d4 ইউনিক্স যুগের প্রথম থেকে সেকেন্ডের প্রতিনিধিত্ব করে,
  • 4e5f6g7 মেশিন শনাক্তকারীকে উপস্থাপন করে,
  • h8i9 প্রক্রিয়া আইডি উপস্থাপন করে
  • j1k2l3 একটি এলোমেলো মান দিয়ে শুরু করে, কাউন্টারকে উপস্থাপন করে।

যেহেতু কাউন্টারটি অনন্য হয়ে উঠবে যদি আমরা একই মেশিনে ডেটা সংরক্ষণ করি আমরা কোনও সন্দেহ ছাড়াই এটি পেতে পারি যে এটি নকল হবে।

সুতরাং সংক্ষিপ্ত ইউআরএল কাউন্টার হবে এবং এখানে একটি কোড স্নিপেট ধরে নেওয়া হচ্ছে যে ধরে নেওয়া হচ্ছে যে আপনার সার্ভারটি সঠিকভাবে চলছে।

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// Create a schema
const shortUrl = new Schema({
    long_url: { type: String, required: true },
    short_url: { type: String, required: true, unique: true },
  });
const ShortUrl = mongoose.model('ShortUrl', shortUrl);

// The user can request to get a short URL by providing a long URL using a form

app.post('/shorten', function(req ,res){
    // Create a new shortUrl */
    // The submit form has an input with longURL as its name attribute.
    const longUrl = req.body["longURL"];
    const newUrl = ShortUrl({
        long_url : longUrl,
        short_url : "",
    });
    const shortUrl = newUrl._id.toString().slice(-6);
    newUrl.short_url = shortUrl;
    console.log(newUrl);
    newUrl.save(function(err){
        console.log("the new URL is added");
    })
});

1
কোনও আরডিবিএমএস কীভাবে কোনও এনএসএল / কী-মান স্টোরের চেয়ে ভাল হবে?
kjs3

@ কেজেএস 3 হ্যাঁ আপনি ঠিকই বলেছেন, যেহেতু অন্যান্য টেবিলের সাথে কোনও সম্পর্ক নেই, আরডিবিএমএসের প্রয়োজন নেই এবং একটি মূল্যের স্টোর দ্রুততর হবে।
ফিরস ওমরনে

4

সি # সংস্করণ:

public class UrlShortener 
{
    private static String ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    private static int    BASE     = 62;

    public static String encode(int num)
    {
        StringBuilder sb = new StringBuilder();

        while ( num > 0 )
        {
            sb.Append( ALPHABET[( num % BASE )] );
            num /= BASE;
        }

        StringBuilder builder = new StringBuilder();
        for (int i = sb.Length - 1; i >= 0; i--)
        {
            builder.Append(sb[i]);
        }
        return builder.ToString(); 
    }

    public static int decode(String str)
    {
        int num = 0;

        for ( int i = 0, len = str.Length; i < len; i++ )
        {
            num = num * BASE + ALPHABET.IndexOf( str[(i)] ); 
        }

        return num;
    }   
}

4

আপনি পুরো ইউআরএল হ্যাশ করতে পারেন, তবে আপনি যদি কেবল আইডিটি সংক্ষিপ্ত করতে চান তবে মার্সেলের পরামর্শ অনুসারে করুন। আমি এই পাইথন বাস্তবায়নটি লিখেছি:

https://gist.github.com/778542


4

আমি ডাটাবেসে ডোমেন প্রতি ইন্টিজার সিকোয়েন্স বাড়িয়ে রাখি এবং URL এর মধ্যে পূর্ণসংখ্যাকে এনকোড করতে হ্যাশিড ব্যবহার করি

static hashids = Hashids(salt = "my app rocks", minSize = 6)

চরিত্রের দৈর্ঘ্য অবসন্ন না হওয়া পর্যন্ত এটি কতক্ষণ সময় নেয় তা দেখতে আমি একটি স্ক্রিপ্ট চালিয়েছি। ছয় অক্ষরের জন্য এটি 164,916,224লিঙ্কগুলি করতে পারে এবং তারপরে সাতটি অক্ষর পর্যন্ত যায়। Bitly সাতটি অক্ষর ব্যবহার করে। পাঁচটি অক্ষরের নীচে আমার কাছে অদ্ভুত লাগছে।

হ্যাশিডগুলি ইউআরএল পাথটি পূর্ণসংখ্যার পিছনে ডিকোড করতে পারে তবে একটি সহজ সমাধান সম্পূর্ণ সংক্ষিপ্ত লিঙ্কটিকে sho.rt/ka8ds3প্রাথমিক কী হিসাবে ব্যবহার করা ।

এখানে সম্পূর্ণ ধারণাটি রয়েছে:

function addDomain(domain) {
    table("domains").insert("domain", domain, "seq", 0)
}

function addURL(domain, longURL) {
    seq = table("domains").where("domain = ?", domain).increment("seq")
    shortURL = domain + "/" + hashids.encode(seq)
    table("links").insert("short", shortURL, "long", longURL)
    return shortURL
}

// GET /:hashcode
function handleRequest(req, res) {
    shortURL = req.host + "/" + req.param("hashcode")
    longURL = table("links").where("short = ?", shortURL).get("long")
    res.redirect(301, longURL)
}

3

আপনি যদি চাকাটি পুনরায় উদ্ভাবন করতে না চান ... http://lilurl.sourceforge.net/


1
"দুঃখিত, দেখে মনে হচ্ছে স্প্যামাররা এটি পেয়ে গেছে instead
তাকেশিন

ডেমো সাইটে। সোর্সফোর্স থেকে সোর্স কোডটি এখনও ডাউনলোডযোগ্য।
আলিস্টার বুলম্যান

3
// simple approach

$original_id = 56789;

$shortened_id = base_convert($original_id, 10, 36);

$un_shortened_id = base_convert($shortened_id, 36, 10);

2
alphabet = map(chr, range(97,123)+range(65,91)) + map(str,range(0,10))

def lookup(k, a=alphabet):
    if type(k) == int:
        return a[k]
    elif type(k) == str:
        return a.index(k)


def encode(i, a=alphabet):
    '''Takes an integer and returns it in the given base with mappings for upper/lower case letters and numbers 0-9.'''
    try:
        i = int(i)
    except Exception:
        raise TypeError("Input must be an integer.")

    def incode(i=i, p=1, a=a):
        # Here to protect p.                                                                                                                                                                                                                
        if i <= 61:
            return lookup(i)

        else:
            pval = pow(62,p)
            nval = i/pval
            remainder = i % pval
            if nval <= 61:
                return lookup(nval) + incode(i % pval)
            else:
                return incode(i, p+1)

    return incode()



def decode(s, a=alphabet):
    '''Takes a base 62 string in our alphabet and returns it in base10.'''
    try:
        s = str(s)
    except Exception:
        raise TypeError("Input must be a string.")

    return sum([lookup(i) * pow(62,p) for p,i in enumerate(list(reversed(s)))])a

যার প্রয়োজন এর জন্য আমার সংস্করণটি এখানে।


1

আপনার আইডিটিকে কেবল একটি স্ট্রিংয়ে অনুবাদ করবেন না কেন? আপনার কেবল এমন একটি ফাংশন দরকার যা একটি অক্ষর (উচ্চ / নিম্ন কেস) বা অঙ্কের মধ্যে 0 এবং 61 এর মধ্যে একটি মানচিত্রের মানচিত্রের প্রয়োজন। তারপরে 4-বর্ণের কোডগুলি তৈরি করতে, বলার জন্য এটি প্রয়োগ করুন এবং আপনার 14.7 মিলিয়ন ইউআরএল কভার হয়েছে।


সরল চিন্তাভাবনার জন্য +1। এটা সত্যিই যে সহজ। আমি ঠিক একটি উত্তর পোস্ট করেছি যা ঠিক এটি করছে। আমার কাছে এমন কিছু প্রোডাকশন কোড রয়েছে যা ডুপ্লিকেট স্ট্রিং নেই এবং সব কিছু অনন্য ensure
অ্যান্ড্রু রিজ

1

এখানে পিএইচপি-র জন্য একটি শুভ ইউআরএল এনকোডিং কার্যক্রম রয়েছে ...

// From http://snipplr.com/view/22246/base62-encode--decode/
private function base_encode($val, $base=62, $chars='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
    $str = '';
    do {
        $i = fmod($val, $base);
        $str = $chars[$i] . $str;
        $val = ($val - $i) / $base;
    } while($val > 0);
    return $str;
}

1

কেউ এই দরকারী খুঁজে পাবে কিনা তা জানেন না - এটি একটি 'হ্যাক এন স্ল্যাশ' পদ্ধতির বেশি, তবুও সহজ এবং যদি আপনি কেবল নির্দিষ্ট অক্ষর চান তবে খুব সুন্দর কাজ করে।

$dictionary = "abcdfghjklmnpqrstvwxyz23456789";
$dictionary = str_split($dictionary);

// Encode
$str_id = '';
$base = count($dictionary);

while($id > 0) {
    $rem = $id % $base;
    $id = ($id - $rem) / $base;
    $str_id .= $dictionary[$rem];
}


// Decode
$id_ar = str_split($str_id);
$id = 0;

for($i = count($id_ar); $i > 0; $i--) {
    $id += array_search($id_ar[$i-1], $dictionary) * pow($base, $i - 1);
} 

1

আপনি O, 0 এবং আমি উদ্দেশ্য অনুসারে বাদ দিয়েছি?

আমি সবেমাত্র রায়ের সমাধানের ভিত্তিতে একটি পিএইচপি ক্লাস তৈরি করেছি।

<?php

    $shorty = new App_Shorty();

    echo 'ID: ' . 1000;
    echo '<br/> Short link: ' . $shorty->encode(1000);
    echo '<br/> Decoded Short Link: ' . $shorty->decode($shorty->encode(1000));


    /**
     * A nice shorting class based on Ryan Charmley's suggestion see the link on Stack Overflow below.
     * @author Svetoslav Marinov (Slavi) | http://WebWeb.ca
     * @see http://stackoverflow.com/questions/742013/how-to-code-a-url-shortener/10386945#10386945
     */
    class App_Shorty {
        /**
         * Explicitly omitted: i, o, 1, 0 because they are confusing. Also use only lowercase ... as
         * dictating this over the phone might be tough.
         * @var string
         */
        private $dictionary = "abcdfghjklmnpqrstvwxyz23456789";
        private $dictionary_array = array();

        public function __construct() {
            $this->dictionary_array = str_split($this->dictionary);
        }

        /**
         * Gets ID and converts it into a string.
         * @param int $id
         */
        public function encode($id) {
            $str_id = '';
            $base = count($this->dictionary_array);

            while ($id > 0) {
                $rem = $id % $base;
                $id = ($id - $rem) / $base;
                $str_id .= $this->dictionary_array[$rem];
            }

            return $str_id;
        }

        /**
         * Converts /abc into an integer ID
         * @param string
         * @return int $id
         */
        public function decode($str_id) {
            $id = 0;
            $id_ar = str_split($str_id);
            $base = count($this->dictionary_array);

            for ($i = count($id_ar); $i > 0; $i--) {
                $id += array_search($id_ar[$i - 1], $this->dictionary_array) * pow($base, $i - 1);
            }
            return $id;
        }
    }
?>

হ্যাঁ. আপনি ক্লাস ঘোষণার ঠিক নীচে মন্তব্যটি দেখেছেন?
স্বেটোস্লাভ মেরিনভ

1

একবার দেখে এ নিন https://hashids.org/ এটা ওপেন সোর্স এবং অনেক ভাষায় রয়েছে।

তাদের পৃষ্ঠাতে অন্যান্য পদ্ধতির কিছু অসুবিধার রূপরেখা দেওয়া হয়েছে।


0

এটি আমি ব্যবহার করি:

# Generate a [0-9a-zA-Z] string
ALPHABET = map(str,range(0, 10)) + map(chr, range(97, 123) + range(65, 91))

def encode_id(id_number, alphabet=ALPHABET):
    """Convert an integer to a string."""
    if id_number == 0:
        return alphabet[0]

    alphabet_len = len(alphabet) # Cache

    result = ''
    while id_number > 0:
        id_number, mod = divmod(id_number, alphabet_len)
        result = alphabet[mod] + result

    return result

def decode_id(id_string, alphabet=ALPHABET):
    """Convert a string to an integer."""
    alphabet_len = len(alphabet) # Cache
    return sum([alphabet.index(char) * pow(alphabet_len, power) for power, char in enumerate(reversed(id_string))])

এটি খুব দ্রুত এবং দীর্ঘ পূর্ণসংখ্যার নিতে পারে।


0

একটি অনুরূপ প্রকল্পের জন্য, একটি নতুন কী পাওয়ার জন্য, আমি একটি র্যান্ডম স্ট্রিং জেনারেটরের চারপাশে একটি মোড়ক ফাংশন করি যা জেনারেটরকে কল করে যতক্ষণ না আমার স্ট্রিংটি পাওয়া যায় যা ইতিমধ্যে আমার হ্যাশটেবলে ব্যবহার করা হয়নি। আপনার নামের স্থানটি পূর্ণ হতে শুরু করলে এই পদ্ধতিটি ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে নামবে তবে আপনি যেমনটি বলেছেন মাত্র 6 টি অক্ষর দিয়েও আপনার কাজ করার মতো প্রচুর নাম স্থান রয়েছে name


এই পন্থাটি কি দীর্ঘমেয়াদে আপনার জন্য কার্যকর হয়েছে?
ক্রিস

সত্যি কথা বলতে কি, আমি সেখানে কোন প্রকল্পটি উল্লেখ করছি সে সম্পর্কে আমার কোনও ধারণা নেই :
জোয়েল বার্গার

0

আমার সমস্যার বৈচিত্র রয়েছে, এতে আমি বিভিন্ন লেখকের ওয়েব পৃষ্ঠাগুলি সঞ্চয় করি এবং অনুমানের দ্বারা পৃষ্ঠাগুলির আবিষ্কার প্রতিরোধ করা দরকার। সুতরাং আমার সংক্ষিপ্ত ইউআরএলগুলি পৃষ্ঠা নম্বরটির জন্য বেস -২২ স্ট্রিংয়ে কয়েকটি অতিরিক্ত সংখ্যা যুক্ত করে। এই অতিরিক্ত অঙ্কগুলি পৃষ্ঠা রেকর্ডে থাকা তথ্য থেকেই তৈরি হয়েছে এবং তারা নিশ্চিত করে যে 3844 টির মধ্যে 1 টির মধ্যে বৈধ রয়েছে (2-সংখ্যার বেস -২২ ধরে)। আপনি একটি প্রান্তরেখা বর্ণনা দেখতে পারেন http://mgscan.com/MBWL


0

খুব ভাল উত্তর, আমি বিজেএফের একটি গোলং বাস্তবায়ন তৈরি করেছি:

package bjf

import (
    "math"
    "strings"
    "strconv"
)

const alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

func Encode(num string) string {
    n, _ := strconv.ParseUint(num, 10, 64)
    t := make([]byte, 0)

    /* Special case */
    if n == 0 {
        return string(alphabet[0])
    }

    /* Map */
    for n > 0 {
        r := n % uint64(len(alphabet))
        t = append(t, alphabet[r])
        n = n / uint64(len(alphabet))
    }

    /* Reverse */
    for i, j := 0, len(t) - 1; i < j; i, j = i + 1, j - 1 {
        t[i], t[j] = t[j], t[i]
    }

    return string(t)
}

func Decode(token string) int {
    r := int(0)
    p := float64(len(token)) - 1

    for i := 0; i < len(token); i++ {
        r += strings.Index(alphabet, string(token[i])) * int(math.Pow(float64(len(alphabet)), p))
        p--
    }

    return r
}

গিথুব এ হোস্ট করা হয়েছে: https://github.com/xor-gate/go-bjf


0
/**
 * <p>
 *     Integer to character and vice-versa
 * </p>
 *  
 */
public class TinyUrl {

    private final String characterMap = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    private final int charBase = characterMap.length();

    public String covertToCharacter(int num){
        StringBuilder sb = new StringBuilder();

        while (num > 0){
            sb.append(characterMap.charAt(num % charBase));
            num /= charBase;
        }

        return sb.reverse().toString();
    }

    public int covertToInteger(String str){
        int num = 0;
        for(int i = 0 ; i< str.length(); i++)
            num += characterMap.indexOf(str.charAt(i)) * Math.pow(charBase , (str.length() - (i + 1)));

        return num;
    }
}

class TinyUrlTest{

    public static void main(String[] args) {
        TinyUrl tinyUrl = new TinyUrl();
        int num = 122312215;
        String url = tinyUrl.covertToCharacter(num);
        System.out.println("Tiny url:  " + url);
        System.out.println("Id: " + tinyUrl.covertToInteger(url));
    }
}

0

স্কালায় বাস্তবায়ন:

class Encoder(alphabet: String) extends (Long => String) {

  val Base = alphabet.size

  override def apply(number: Long) = {
    def encode(current: Long): List[Int] = {
      if (current == 0) Nil
      else (current % Base).toInt :: encode(current / Base)
    }
    encode(number).reverse
      .map(current => alphabet.charAt(current)).mkString
  }
}

class Decoder(alphabet: String) extends (String => Long) {

  val Base = alphabet.size

  override def apply(string: String) = {
    def decode(current: Long, encodedPart: String): Long = {
      if (encodedPart.size == 0) current
      else decode(current * Base + alphabet.indexOf(encodedPart.head),encodedPart.tail)
    }
    decode(0,string)
  }
}

স্কেলা পরীক্ষার সাথে পরীক্ষার উদাহরণ:

import org.scalatest.{FlatSpec, Matchers}

class DecoderAndEncoderTest extends FlatSpec with Matchers {

  val Alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

  "A number with base 10" should "be correctly encoded into base 62 string" in {
    val encoder = new Encoder(Alphabet)
    encoder(127) should be ("cd")
    encoder(543513414) should be ("KWGPy")
  }

  "A base 62 string" should "be correctly decoded into a number with base 10" in {
    val decoder = new Decoder(Alphabet)
    decoder("cd") should be (127)
    decoder("KWGPy") should be (543513414)
  }

}

0

জিয়নক্রস ক্লাস ভিত্তিক ফাংশন

function shortly($input){
$dictionary = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9'];
if($input===0)
    return $dictionary[0];
$base = count($dictionary);
if(is_numeric($input)){
    $result = [];
    while($input > 0){
        $result[] = $dictionary[($input % $base)];
        $input = floor($input / $base);
    }
    return join("", array_reverse($result));
}
$i = 0;
$input = str_split($input);
foreach($input as $char){
    $pos = array_search($char, $dictionary);
    $i = $i * $base + $pos;
}
return $i;
}

0

এখানে একটি নোড.জেএস বাস্তবায়ন যা সম্ভবত বিট.ইল. একটি অত্যন্ত এলোমেলো সাত-অক্ষরের স্ট্রিং উত্পন্ন।

এটি এলোমেলোভাবে সাতটি অক্ষর বাছাইয়ের পরিবর্তে অত্যন্ত র‌্যান্ডম 25 টি চরসেট তৈরি করতে নোড.জেএস ক্রিপ্টো ব্যবহার করে।

var crypto = require("crypto");
exports.shortURL = new function () {
    this.getShortURL = function () {
        var sURL = '',
            _rand = crypto.randomBytes(25).toString('hex'),
            _base = _rand.length;
        for (var i = 0; i < 7; i++)
            sURL += _rand.charAt(Math.floor(Math.random() * _rand.length));
        return sURL;
    };
}

"বিট.লাই" বলতে আপনার অর্থ কী? ?
পিটার মর্টেনসেন

0

আমার পাইথন 3 সংস্করণ

base_list = list("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
base = len(base_list)

def encode(num: int):
    result = []
    if num == 0:
        result.append(base_list[0])

    while num > 0:
        result.append(base_list[num % base])
        num //= base

    print("".join(reversed(result)))

def decode(code: str):
    num = 0
    code_list = list(code)
    for index, code in enumerate(reversed(code_list)):
        num += base_list.index(code) * base ** index
    print(num)

if __name__ == '__main__':
    encode(341413134141)
    decode("60FoItT")

0

একটি মানের নোড.জেএস / জাভাস্ক্রিপ্ট সমাধানের জন্য, আইডি-শর্টনার মডিউলটি দেখুন, যা পুরোপুরি পরীক্ষা করা হয়েছে এবং কয়েক মাস ধরে উত্পাদনে ব্যবহৃত হচ্ছে।

এটি একটি দক্ষ ID / URL Shortener এ খেলাপি প্লাগেবল স্টোরেজ সমর্থন প্রদান করে Redis , এবং আপনি এমনকি আপনার সংক্ষিপ্ত আইডি অক্ষর সেট কাস্টমাইজ করতে পারেন কিনা সংক্ষেপিত হয় idempotent । এটি একটি গুরুত্বপূর্ণ পার্থক্য যা সমস্ত ইউআরএল সংক্ষিপ্তকারীরা বিবেচনা করে না।

এখানে অন্যান্য উত্তরের সাথে সম্পর্কিত, এই মডিউলটি উপরের মার্কেল জ্যাকওয়ার্থের দুর্দান্ত স্বীকৃত উত্তরটি কার্যকর করে।

সমাধানের মূলটি নিম্নলিখিত রেডিস লুয়া স্নিপেট দ্বারা সরবরাহ করা হয়েছে :

local sequence = redis.call('incr', KEYS[1])

local chars = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ_abcdefghijkmnopqrstuvwxyz'
local remaining = sequence
local slug = ''

while (remaining > 0) do
  local d = (remaining % 60)
  local character = string.sub(chars, d + 1, d + 1)

  slug = character .. slug
  remaining = (remaining - d) / 60
end

redis.call('hset', KEYS[2], slug, ARGV[1])

return slug

0

কেন কেবল একটি এলোমেলো স্ট্রিং উত্পন্ন করে বেস URL এ যুক্ত করবেন না? এটি সি # তে এটি করার একটি খুব সরলিকৃত সংস্করণ ।

static string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
static string baseUrl = "https://google.com/";

private static string RandomString(int length)
{
    char[] s = new char[length];
    Random rnd = new Random();
    for (int x = 0; x < length; x++)
    {
        s[x] = chars[rnd.Next(chars.Length)];
    }
    Thread.Sleep(10);

    return new String(s);
}

তারপরে কেবল বেসলআরএল এ এলোমেলো স্ট্রিং যুক্ত করুন:

string tinyURL = baseUrl + RandomString(5);

মনে রাখবেন এটি এটি করার একটি খুব সরল সংস্করণ এবং এটি র্যান্ডমস্ট্রিং পদ্ধতিটি সদৃশ স্ট্রিং তৈরি করতে পারে। উত্পাদনে আপনি সদৃশ স্ট্রিংগুলির জন্য অ্যাকাউন্টটি নিতে চান আপনার সর্বদা একটি অনন্য URL থাকবে have আমার কাছে এমন কিছু কোড রয়েছে যা ডাটাবেস টেবিলটি জিজ্ঞাসা করে ডুপ্লিকেট স্ট্রিংগুলির জন্য অ্যাকাউন্ট গ্রহণ করে যদি কেউ আগ্রহী হয় তবে আমি ভাগ করতে পারি।


0

এটি আমার প্রাথমিক চিন্তা, এবং আরও চিন্তাভাবনা করা যায়, বা এটি ভালভাবে কাজ করে বা কোনও উন্নতির প্রয়োজন কিনা তা দেখার জন্য কিছু সিমুলেশন করা যেতে পারে:

আমার উত্তরটি হ'ল ডাটাবেসে লম্বা ইউআরএলটি মনে রাখা, এবং আইডিটি ব্যবহার 0করতে 9999999999999999(বা তবে বড় সংখ্যাটি প্রয়োজন হয়)।

তবে 0 আইডি 9999999999999999একটি সমস্যা হতে পারে, কারণ

  1. যদি আমরা হেক্সাডেসিমাল, এমনকি বেস 62 বা বেস 64 ব্যবহার করি তবে এটি সংক্ষিপ্ত হতে পারে। (করুন Base64- ঠিক YouTube ব্যবহার A- Z a- z 0- 9 _এবং- )
  2. যদি তা থেকে বৃদ্ধি 0করার জন্য 9999999999999999অবিশেষে, তারপর হ্যাকার, যাতে তাদের এ যান এবং জানেন URL গুলি মানুষ একে অপরের কি পাঠাচ্ছেন পারে, তাই এটা একটি গোপনীয়তা সমস্যা হতে পারে

আমরা এটা করতে পারি:

  1. একটি সার্ভার বরাদ্দ 0আছে999 আছে, সার্ভার এ, তাই এখন সার্ভার এ-তে এমন 1000 আইডি রয়েছে। সুতরাং যদি 20 বা 200 সার্ভার ক্রমাগত নতুন আইডি চায়, তবে এটি প্রতিটি নতুন আইডি জিজ্ঞাসা করতে হবে না, বরং একবার 1000 আইডির জন্য জিজ্ঞাসা করবে
  2. আইডি 1 এর জন্য, উদাহরণস্বরূপ, বিটগুলি বিপরীত করুন। তাই 000...00000001হয়ে যায় 10000...000, যাতে যখন বেস 64 এ রূপান্তরিত হয়, এটি প্রতিবার অ-অভিন্ন আইডি বাড়িয়ে তুলবে।
  3. চূড়ান্ত আইডিগুলির জন্য বিটগুলি ফ্লিপ করতে এক্সওআর ব্যবহার করুন। উদাহরণস্বরূপ, এক্সওআর 0xD5AA96...2373(একটি গোপন কী হিসাবে) এবং কিছু বিট উল্টানো হবে। (যখনই গোপন কীতে 1 বিট রয়েছে, এটি আইডির বিটটি ফ্লিপ করবে)। এটি আইডিগুলি অনুমান করা আরও শক্ত করে তুলবে এবং আরও এলোমেলোভাবে প্রদর্শিত হবে

এই স্কিম অনুসরণ করে, একক সার্ভার যা আইডিগুলি বরাদ্দ করে তা আইডি তৈরি করতে পারে এবং তাই 20 বা 200 সার্ভার আইডি বরাদ্দের অনুরোধ করতে পারে। দু'জন অনুরোধকারী সার্ভারকে একই ব্যাচটি পেতে বাধা দেওয়ার জন্য বরাদ্দকারী সার্ভারকে একটি লক / সেমফোর ব্যবহার করতে হবে (বা যদি এটি একবারে একটি সংযোগ গ্রহণ করে, এটি ইতিমধ্যে সমস্যার সমাধান করে)। সুতরাং আমরা বরাদ্দ পাওয়ার জন্য অপেক্ষা করার জন্য লাইনটি (সারি) খুব দীর্ঘ হওয়া চাই না। সুতরাং একসাথে 1000 বা 10000 বরাদ্দ করা সমস্যার সমাধান করতে পারে।

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