لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 09/04/21 في كل الموقع
-
لدي بيانات على هيئة series في pandas كالتالي: df = pd.Series(['cat','hat','bat','dog','ant']) وأود البحث عن الكلمات التي تحتوي علي المقطع "og" والمقطع "at" كيف يمكنني فعل هذا؟3 نقاط
-
شو الفرق بين container , container-fluid في بوتستراب يعني اريد شرح مفصل للفرق بينهما3 نقاط
-
لدي مشروع مبني من خلال node.js وفيه العديد من المكتبات التي تم الاعتماد عليها لبناء المشروع، ومنها ما أصبح قديم لذلك أحتاج لتعديل بعض النسخ من هذه المكتبات التي لم تعد تعمل بالشكل الصحيح. كيف يمكنني الحصول على نسخ هذه المكتبات ضمن المشروع والتي تحتاج لتحديث، وبعد ذلك كيف يمكنني تحديثها؟2 نقاط
-
أعمل على مشروع يتطلّب حصراً النسخة 12 ومافوق من node.js لكي يعمل بالشكل الصحيح. هل يوجد طريقة تمكنني من تحديد رقم النسخة ضمن package.json وبالتالي عندما يقوم باقي المطورين بتحميل حزم المشروع يتم تنبيههم إلى ضرورة وجود هذه النسخة أو في حال يجب عليهم تحديث النسخة الحالية؟2 نقاط
-
لدي حقل في نموذج واحد، كالتالي: class Video(models.Model): date = fields.DateField(auto_now=False) الآن، أحتاج إلى تصفية الكائنات حسب النطاق الزمني. كيف أقوم بتصفية جميع الكائنات التي لها تاريخ بين 1 أغسطس 2021 و 31 أغسطس 2021؟2 نقاط
-
لدي نموذج كالتالي: class User(models.Model): name = models.CharField(max_length=200) bio = models.CharField(max_length=20000, blank=True) GENDER_CHOICES = ( ('M', 'Male'), ('F', 'Female'), ) gender = models.CharField(max_length=20, choices=GENDER_CHOICES) وأستخدم النموذج السابق في ملف العرض view التالي: def profile(request): users = User.objects.filter(bio='') return object_list(request, template_name='polls/profiles.html', queryset=users, paginate_by=5) لكن المشكلة هي عندما أحاول أن أقوم بطباعة الخاصية gender أحصل على M أو F بدلًا من Male أو Female، كيف أقوم بطباعة اسم الخاصية بالكامل؟2 نقاط
-
ما الفرق بين إستخدام الarraylist او ال linkedlist خاصة إن كﻻهما يتم إستخدامه بنفس الطريقة2 نقاط
-
CSS Loader و Style Loader هما محملان webpack. لم أستطع فهم الفرق بين الاثنين. لماذا يتعين علي استخدام محملتين عندما يقوم كلاهما بنفس المهمة؟2 نقاط
-
هل يمكن أستبدال Node.js بـ Django في تطبيقات React Native و اذا كانت الاجابة نعم ايهما افضل للأستخدام بالنسبة لتطبيقات الويب و الموبايل ؟2 نقاط
-
هذا فقط سؤال يمكنك أنت (أو أنت وفريقك) الإجابة عليه. السؤال الحقيقي هو ، "ما هي المشكلة التي أحلها وما هي التكنولوجيا الأنسب للوظيفة؟" في الحقيقة ما يفشل كل مطور في رؤيته هو أن اللغة أو التكنولوجيا هي مجرد أداة ولمساعدتك في تحديد الأولويات يمكن طرح الأمر كالتالي Django هو الخيار الأقوى إذا: أنت بحاجة إلى إنشاء تطبيقك بسرعة كبيرة - أسلوب Django الخفيف في الشفرة مثالي لذلك. كنت تبحث عن أمان مدمج في بنية الشفرة نفسها. تعتقد أنك قد تدمج تقنيات جديدة مثل التعلم الآلي في وقت ما في المستقبل. Node هو الخيار الأقوى إذا: أنت تعطي الأولوية للمرونة والإبداع على السرعة في عملية التطوير. كنت تبحث عن أداء فائق السرعة وتطبيقك ليس ثقيلًا في وحدة المعالجة المركزية. الواجهة الأمامية مكتوبة بلغة جافا سكريبت وترغب في تحقيق مكاسب من حيث التكلفة والإنتاجية من كل شخص يعمل بنفس اللغة. يمكنك الأن تحديد ما تريد وتختار على أساسه2 نقاط
-
كيف نستهدف الرابط النشط في Next.js مثل الطريقة التي نقوم بها في React-Router؟ بمعنى ، أعطي الرابط النشط class عندما يكون مساره نشطًا؟2 نقاط
-
2 نقاط
-
يمكنك أن تستعمل أي لغة خاصة بالواجهات الخلفية Backend و أي إطار عمل ترغب به (أو حتى بدون إطار عمل على الإطلاق)، وهنا بعض الأمثلة: PHP مع إطار العمل Laravel: تعد لغة PHP أشهر لغة للواجهات الخلفية في الوقت الحالي، كما أن Laravel هو أكثر إطار عمل مستخدم أيضًا، لغة PHP مجهزة بالفعل لخوادم الويب، لأنها صممت في الأساس لهذا الغرض، كما أن إطار العمل Laravel يوفر لك بنية سهلة وبسيطة لعمل API للتطبيقات أو البرامج بسهولة، كما يوفر لك نظام إستيثاق Authentication مُعد بالفعل ولن تحتاج إلى ضبط أي شيء، وهو يتبع نظام MVC مما يوفر لك تنظيم للكود والملفات أيضًا. لغة PHP مستخدمه في Facebook و Wikipedia وغيرها. Node.js مع إطار العمل Express.js: إزدادت في الفترة الأخيرة شعبية لغة JavaScript خصوصًا في الواجهات الخلفية، حيث أصبح هناك مسار لتعلم تطوير المواقع يسمى MERN (MongoDB - Express.js - React.js - Node.js)، لكن يمكنك أن تستخدم أي نوع من قواعد البيانات وليس شرطًا أن تستعمل MongoDB، ويمكنك أن تقوم بعمل API به أيضًا. إطار العمل Express.js مستخدم في شركات مثل Uber و Yandex و IBM وغيرها. Python مع إطار العمل Django: لغة Python من أسهل اللغات في التعلم ومن أسهلها في كتابة الكود، ولها العديد من المميزات، كما أن إطار العمل Django يوفر لك بنية أولية مجهزة لتقوم ببناء أي مشروع به، ويمكنك أن تقوم بعمل API أيضًا به بكل سهولة بسبب مميزات JSON وXML التي يقدمها. إطار العمل Django يتم إستعماله في Disqus و Instagram و Spotify و YouTube و DropBox و Pinterest و غيرها. يمكنك أن تستعمل أي لغة من اللغات السابقة (أو غيرها حتى)، فكل هذه اللغات يمكنها أن تقوم بكل ما تريده وأكثر وبسهولة أيضًا. كما يمكنك أن تختار أحد إطارات العمل التي ذكرتها أو تستخدم إطارات عمل أخرى، ولكني ذكرت فقط الأكثر شهرة وإستخدامًا في هذه اللغات. ويوجد في الأكاديمية مقالة حول الفرق بين Laravel و Django وكذلك Rails: بالنسبة لقاعدة البيانات، فلا أنصحك بأن تستخدم SQLite موقع حقيقي أو لحفظ وإسترجاع البيانات بسرعة، بدلًا من ذلك يمكنك أن تستخدم MySQL أو Postgres، وهنا مقالة تتمحور حول عيوب ومميزات كل نوع من الأنواع السابقة:2 نقاط
-
الإصدار 1.0.0
116569 تنزيل
سطع نجم لغة البرمجة بايثون في الآونة الأخيرة حتى بدأت تزاحم أقوى لغات البرمجة في الصدارة وذاك لمزايا هذه اللغة التي لا تنحصر أولها سهولة كتابة وقراءة شيفراتها حتى أصبحت الخيار الأول بين يدي المؤسسات الأكاديمية والتدريبية لتدريسها للطلاب الجدد الراغبين في الدخول إلى مجال علوم الحاسوب والبرمجة. أضف إلى ذلك أن بايثون لغةً متعدَّدة الأغراض والاستخدامات، لذا فهي دومًا الخيار الأول في شتى مجالات علوم الحاسوب الصاعدة مثل الذكاء الصنعي وتعلم الآلة وعلوم البيانات وغيرها، كما أنَّها مطلوبة بشدة في سوق العمل وتعتمدها كبرى الشركات التقنية. دورة تطوير التطبيقات باستخدام لغة Python احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة اشترك الآن بني هذا العمل على كتاب «How to code in Python» لصاحبته ليزا تاغليفيري (Lisa Tagliaferri) وترجمه إلى العربية محمد بغات وعبد اللطيف ايمش، وحرره جميل بيلوني، ويأتي شارحًا المفاهيم البرمجية الأساسية بلغة بايثون، ونأمل في أكاديمية حسوب أن يكون إضافةً نافعةً للمكتبة العربيَّة وأن يفيد القارئ العربي في أن يكون منطلقًا للدخول إلى عالم البرمجة من أوسع أبوابه. رُبط هذا الكتاب مع توثيق لغة بايثون في موسوعة حسوب لتسهيل عملية الاطلاع على أي جزء من اللغة مباشرة وقراءة التفاصيل باللغة العربية. هذا الكتاب مرخص بموجب رخصة المشاع الإبداعي Creative Commons «نسب المُصنَّف - غير تجاري - الترخيص بالمثل 4.0». يمكنك قراءة فصول الكتاب على شكل مقالات من هذه الصفحة، «المرجع الشامل إلى تعلم لغة بايثون»، أو مباشرةً من الآتي: المقال الأول: دليل تعلم بايثون اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3 المقال الثاني: تثبيت بايثون 3 وإعداد بيئتها البرمجية المقال الثالث: كيف تكتب أول برنامج لك المقال الرابع: كيفية استخدام سطر أوامر بايثون التفاعلي المقال الخامس: كيفية كتابة التعليقات المقال السادس: فهم أنواع البيانات المقال السابع: مدخل إلى التعامل مع السلاسل النصية المقال الثامن: كيفية تنسيق النصوص المقال التاسع: مقدمة إلى دوال التعامل مع السلاسل النصية المقال العاشر: آلية فهرسة السلاسل النصية وطريقة تقسيمها المقال الحادي عشر: كيفية التحويل بين أنواع البيانات المقال الثاني عشر: كيفية استخدام المتغيرات المقال الثالث عشر: كيفية استخدام آلية تنسيق السلاسل النصية المقال الرابع عشر: كيفية إجراء العمليات الحسابية المقال الخامس عشر: الدوال الرياضية المضمنة المقال السادس عشر: فهم العمليات المنطقية المقال السابع عشر: مدخل إلى القوائم المقال الثامن عشر: كيفية استخدام توابع القوائم المقال التاسع عشر: فهم كيفية استعمال List Comprehensions المقال العشرون: فهم نوع البيانات Tuples المقال الحادي والعشرين: فهم القواميس المقال الثاني والعشرين: كيفية استيراد الوحدات المقال الثالث والعشرين: كيفية كتابة الوحدات المقال الرابع والعشرين: كيفية كتابة التعليمات الشرطية المقال الخامس والعشرين: كيفية إنشاء حلقات تكرار while المقال السادس والعشرين: كيفية إنشاء حلقات تكرار for المقال السابع والعشرين: كيفية استخدام تعابير break وcontinue وpass عند التعامل مع حلقات التكرار المقال الثامن والعشرين: كيفية تعريف الدوال المقال التاسع والعشرين: كيفية استخدام *args و**kwargs المقال الثلاثين: كيفية إنشاء الأصناف وتعريف الكائنات المقال الحادي والثلاثين: فهم متغيرات الأصناف والنسخ المقال الثاني والثلاثين: وراثة الأصناف المقال الثالث والثلاثين: كيفية تطبيق التعددية الشكلية (Polymorphism) على الأصناف المقال الرابع والثلاثين: كيف تستخدم منقح بايثون المقال الخامس والثلاثين: كيفية تنقيح شيفرات بايثون من سطر الأوامر التفاعلي المقال السادس والثلاثين: كيف تستخدم التسجيل Logging المقال السابع والثلاثين: كيفية ترحيل شيفرة بايثون 2 إلى بايثون 31 نقطة -
الإصدار 1.0.0
47111 تنزيل
يضع هذا الكتاب المُوجز القارئ على أعتاب عالم تصميم تجربة المُستخدمين UX، وهو علم له قواعده وأصوله وأدواته، ويهدف إلى تعريف القارئ المُبتدئ بأساس هذا العلم وكيف يُطبّق على المُنتجات الرّقمية من مواقع ويب خدميّة وتطبيقات على الأجهزة الذّكية وصولًا إلى التّصميم الأمثل الّذي يُوفِّق بين هدف المُستخدم أوّلًا وهدف الخدمة التّجاريّ، الأمر الّذي يعني منتجًا ناجحًا. يبدأ الكتاب بشرح مفاهيم عامة عن تجربة المستخدم ليواصِل مع شرح كيفية إجراء مختلف الدراسات التي يحتاج المصمِّم للقيام بها، ومتطلباتها، ثم الأمور الواجب أخذها بالحسبان عند التصميم لضمان تجربة استخدام مريحة وممتازة، ليختتم في النهاية بالإشارة إلى أهمية الإحصائيات وضرورة الاعتماد عليها، حيث خُصّصت عدة أقسام لهذه النقطة، لتشير إلى مدى أهمية اعتماد بيانات وإحصائيات المستخدمين مثل أساس للتصميم، وكذا أبرز الإحصائيات الممكن التحصل عليها من خلال عدة اختبارات. يمكنك قراءة فصول هذا الكتاب مباشرةً على شكل مقالات، وإليك العناوين: مدخل إلى تجربة المستخدم User Experience فهم ودراسة المستخدمين في مجال تجربة المستخدم دراسة الشريحة المستهدفة في مجال تجربة المستخدم كيفية التصميم للأجهزة المختلفة هندسة المعلومات في تجربة المستخدم تعرف على أنماط التصميم في مجال تجربة المستخدم أشياء لا يمكن اعتبارها رسوما تخطيطية (Wireframes) في مجال تجربة المستخدم تعرف على الرسوم التخطيطية (Wireframes) في مجال تجربة المستخدم مفهوم الثقل المرئي (Visual Weight) والألوان في مجال تجربة المستخدم التكرار ومخالفة الأنماط في مجال تجربة المستخدم المحاذاة والقرب في مجال تجربة المستخدم تعرف على أساليب مسح الواجهة والتراتب المرئي في مجال تجربة المستخدم أساليب الإطلاع في مجال تجربة المستخدم: التصفح، البحث والاكتشاف تصميم هيكل صفحة الويب والعناصر الأساسية في مجال تجربة المستخدم الأزرار، النماذج والدعوات إلى الإجراء في مجال تجربة المستخدم استخدام علم النفس في مجال تجربة المستخدم لتكييف المستخدم وإقناعه كيف تغير الخبرة من تجربة المستخدم؟ تصميم تجربة المستخدم من خلال بيانات وإحصائيات المستخدمين تعرف على أنواع المخططات الإحصائية في مجال تجربة المستخدم اختبارات أ/ب (A/B Test) في مجال تجربة المستخدم1 نقطة -
ما معني هذا 64-bit ARMv8-A (32-bit Mode) و هل هذا يعني إن جهازي 32-bit ام 64-bit و اذا كان الجهاز 32-bit هل هناك طريقه ليصبح 64-bit1 نقطة
-
مرحبا لدي صفحة تحتوي على form للاضافة وعند زيارتها يظهر لي الخطأ window is not defined لكنه لا يشير لشيء معين يسبب المشكلة وهذا هو مكون الصفحة import React, { useState } from 'react'; import { Flex, Box, FormControl, FormLabel, Input, Textarea, Stack, Button, Heading, FormErrorMessage, useColorModeValue, useToast, } from '@chakra-ui/react'; import axios from 'axios'; import { useForm } from 'react-hook-form'; import { useRouter } from 'next/router'; import {Editor} from "react-draft-wysiwyg" import { EditorState, convertToRaw } from 'draft-js'; import draftToHtml from 'draftjs-to-html'; // import htmlToDraft from 'html-to-draftjs'; import 'node_modules/react-draft-wysiwyg/dist/react-draft-wysiwyg.css'; export default function EditorConvertToHTML() { const router = useRouter(); const toast = useToast(); const [state, setState] = useState({ editorState: EditorState.createEmpty(), }); const onEditorStateChange = (editorState) => { setState({ editorState, }); }; const { handleSubmit, register, formState: { errors, isSubmitting }, } = useForm(); async function onSubmit(values, e) { e.preventDefault(); console.log({ ...values, content: draftToHtml(convertToRaw(state.editorState.getCurrentContent())), }); try { const res = await axios.post(`${process.env.NEXT_PUBLIC_API}/article/add`, { ...values, content: draftToHtml(convertToRaw(state.editorState.getCurrentContent())), }); router.push('/'); } catch (error) { console.log(error); toast({ title: 'فشل في عملية الارسال', status: 'error', duration: 9000, // isClosable: true, }); } } //title //description //content //imageUrl return ( <Box> <form onSubmit={handleSubmit(onSubmit)}> <Box p="4" w="50%" mb="8" bg="white"> <FormControl id="email" isInvalid={errors.title}> <FormLabel>العنوان</FormLabel> <Input {...register('title', { required: 'هذا مطلوب', })} /> <FormErrorMessage>{errors.title && errors.title.message}</FormErrorMessage> </FormControl> <FormControl id="email" isInvalid={errors.description}> <FormLabel>وصف</FormLabel> <Textarea {...register('description', { required: 'هذا مطلوب', })} /> <FormErrorMessage>{errors.description && errors.description.message}</FormErrorMessage> </FormControl> <FormControl id="email" isInvalid={errors.imageUrl}> <FormLabel>الصورة</FormLabel> <Input {...register('imageUrl', { required: 'هذا مطلوب', })} /> <FormErrorMessage>{errors.imageUrl && errors.imageUrl.message}</FormErrorMessage> </FormControl> </Box> <Box shadow="md" dir="ltr" w="50%" mb="8" bg="white"> <Editor editorState={state.editorState} wrapperClassName="demo-wrapper" editorClassName="demo-editor" onEditorStateChange={onEditorStateChange} /> </Box> <Box w="50%" bg="white"> <Textarea disabled value={draftToHtml(convertToRaw(state.editorState.getCurrentContent()))} /> </Box> <Button type="submit" isLoading={isSubmitting} isDisabled={isSubmitting} bg={'blue.400'} color={'white'} _hover={{ bg: 'blue.500', }} > سجل الدخول </Button> </form> </Box> ); }1 نقطة
-
أرغب بجعل خادم node.js قيد العمل دوماً حتى في حال إغلاق الاتصال مع الخادم، أي بمعنى آخر عندما أقوم حالياً بإغلاق الـ terminal، يتم أيضاً إيقاف خادم node.js ويتوقف عن استقبال الطلبات من طرف المستخدم. هل يوجد طريقة لجعل الخادم يعمل بشكل دائم حتى في حال الإغلاق؟ وما هو الحل في نظام Unix دون استخدام حزم إضافية مثل pm2 وغيرها؟1 نقطة
-
أحتاج إلى تنفيذسكريبت بلغة Python من خلال Django Shell. حاولت أن أقوم بهذا الأمر بالطريقة التالية: ./manage.py shell << clear_db.py لكنها لم تنجح. ويتوقع سطر الأوامر كتابة شيء ما.1 نقطة
-
أود استخدام قوالب html التي يقدمها webpack عبر HtmlWebpackPlugin. تبدو قوالب html كما يلي: <!DOCTYPE html> [...] <body> <h1 class="text-red-600">Test: include HTML partial with standard lodash functionality</h1> <%= require('./partials/header').default %> </body> </html> header.html <h2>Header in H2 as Test</h2> webpackconfig const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { module { rules: [ { test: /\.html$/, exclude: /node_modules/, use: ['html-loader'] } ] }, plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', template: './src/templates/index.html', }) ] } عند تشغيل npm run dev أحصل على Cannot Get /1 نقطة
-
لقد أعتدت على استخدام npm بشكل مباشر عند تحميل أي حزمة ولكن لاحظت أنه في بعض الأحيان تتطلب بعض الحزم تحميلها من خلال الأمر --save-dev وبالتالي تظهر ضمن قسم devDependencies. لقد قرأت في التوثيق الرسمي ووجدت أيضاً نمط آخر وهو peer ولكن لم أجد شرح كافي عن استخدامات أنماط الحزم الموجودة: dependencies و dev dependencies و peer dependencies. ما هي الفروقات الأساسية فيما بينها؟ وماهي استعمالات كل منها؟1 نقطة
-
إن المعالج لديك هو بنظام 64-bit ولكن نظام التشغيل المثبت على الجهاز هو 32-bit. بشكل عام المعالج يقبل نظام تشغيل 64 بت، وسيعمل إن كان نظام التشغيل الذي سوف تثبته متوافقاً مع بقية مكونات الجهاز.1 نقطة
-
أريد حل هذا السؤال ولكن عندما أظهر الناتج في المتصفح تظهر القيمة الأخيرة فقط, بالرغم من انها تظهر بشكل صحيح في الكونسول ملف main.js : var i; var x = document.getElementById('num'); function typeWord(){ var y = x.value; for( i=y; i>0; i--){ console.log(i); document.getElementById('demo').innerHTML= "<p>"+i+"</p>"; } } بنية الـ html : <div> <label for="">enter your num</label> <input type="number" id="num"> <button onclick=" typeWord();"> type word</button> <h1>The numbers is <span id="demo"></span></h1> </div> New folder.zip1 نقطة
-
السلام عليكم اي الفريم ورك أفضل في الوطن العربي وخصوصا مصر react or angular?1 نقطة
-
ماهو الهدف من استخدام tf.identity في تنسرفلو Tensorflow، لم أفهم الغرض منه، هل يمكن أن يتم توضيح الفائدة منه بمثال؟1 نقطة
-
1 نقطة
-
المشكلة في هذا الكود productPrice =""; productCategory =""; productDesc =""; productName=""; أنت تفرغ المتغيرات وليس الحقول, لتفريغ الحقول يجب استخدام المتغيرات التي أسندتها للحقول , فيكون شكل الكود كالتالي productPriceInput.value=""; productCategoryInput.value=""; productDescInput.value=""; productNameInput.value=""; حدث الصفحة وجرب الأمر1 نقطة
-
أحاول حذف عمود معين من dataframe ، حاولت أستخدام هذا الكود: del df.column_name لكنه لا يعمل، كيف يمكنني عمل هذا؟1 نقطة
-
إضافة لما قدمه سامح يمكنك القيام بما يلي: from copy import deepcopy as c new_obj = c(object_you_want_copied) new_obj.id = None new_obj.save() هذه الطريقة لا تقوم باستدعاء قاعدة البيانات لاسترداد كائن. وهذا يجعلها مفيدة إذا كنت تريد إنشاء نسخة من كائن غير موجود حتى الآن في قاعدة البيانات. وهنا طريقة أخرى أيضاً لاستنساخ كائن: from django.forms import model_to_dict obj = Some.objects.get(slug='something') par = model_to_dict(instance, exclude=['id']) new_obj = Some.objects.create(**par) أو يمكنك استنساخه كالتالي: d = Foo.objects.filter(pk=1).values().first() d.update({'id': None}) duplicate = Foo.objects.create(**d)1 نقطة
-
1 نقطة
-
يمكنك أن تقوم بذلك بأكثر من طريقة وأسهلهم هي من خلال عمل نسخة من الكائن وجعل الـ Primary Key يساوي None، كالتالي: obj = User.objects.get(pk=1) obj.pk = None obj.save() الكود السابق يقوم بجلب instance من الكائن ثم نقوم بجعل الـ id بقيمة None، وبالتالي عند تشغيل التابع save سوف يقوم بعمل صف جديد في قاعدة البيانات. بالطبع يمكنك أن تقوم بتحديث/تعديل الكائم قبل حفظه بشكل طبيعي، كما ينصح توثيق Django أن تقوم بجعل الخاصية _state.adding تساوي True، لكي تتم عملية إنشاء كائن جديد بشكل سليم كالتالي: post = Post(title='My first blogpost', summary='Blogging is easy') post.save() # post.pk == 1 post.pk = None post._state.adding = True post.save() # post.pk == 2 عملية الحفظ الأولى سوف تقوم بإنشاء أول صف في الجدول في قاعدة البيانات، بينما عملية الحفظ الثانية سوف تقوم بعمل صف جديد في نفس الجدول.1 نقطة
-
لا يمكن لأحد الإجابة على مثل هذه الأسئلة إلا إذا أكملت السؤال ب " من حيث " فرص العمل سهولة التعلم المجتمع االأداء وما إلى ذلك وإليك مقارنة بينهما يعتبر ال react مكتبة على عكس angular إطار عمل والفرق بينهم أن angular يوفر لك المكتبات والأدوات الكاملة التي تحتاجها لتطوير التطبيقات أما react في مكتبة تتيح لك إختيار الحزم أو المكتبات الأخرى لتعمل بها مع react يعتبر تعلم react أسهل نسبياً من angular حيث إذا كنت تعلم javascript جيداً فلن يكون هناك صعوبة في تعلمه بينما مع angular نظراً لأنه إطار عمل فستجد الأمر أكثر تعقيداً نسبياً يعتبر عالمياً ال react أكثر طلباُ ولكن أيضاً angular مطلوب و كما هو الحال في مصر يعتبر تطبيقات ال react أقل حجماً من تطبيقات ال react وأسرع بفرق بسيط عن ال angular حيث يعتمد على ال virtual Dom كما أن مع react يتوفر لك react native وهي تقنية قوية لتطوير تطبيقات الهاتف وهي ميزة قوية لذلك يمكنك الإختيار المكتبة المفضلة لك كما يمكنك قراءة الإجابات على هذه الأسئلة1 نقطة
-
أنت لا تحتاج استخدام webpack على الأقل مباشرة في مشاريعك لأن التكنولوجيات المتوفرة حاليا تجهز كل الاحتياجات لك في الخلفية يمكنك ان تحتاج webpack عندما تريد انشاء مشروع من الصفر و لا يوجد سبب في وقتنا هذا يدفعك لذلك غير تعلم التكنولوجيا في حد ذاتها لكنك حتما ستحتاج webpack اذا كنت تطور أشياء يستخدمها المطورين وكمثال على ذلك عندما طورو react وخرج للعلن قامو بانشاء أداة create react app المطورين الذين طورو الأداة كانو بحاجة ماسة ل webpack لذا الأمر يعتمد فقط على احتياجاتك1 نقطة
-
Webpack عبارة عن مُجمّع ملفات ثابتة (مثل الصور وتنسيقات CSS وغيرها) لتطبيقات JavaScript الحديثة. ويوفر Webpack مجموعة كبيرة من الإعدادات والإضافات التي تسهل هذه العملية، كما يوفر Webpack أيضًا ما يسمى المحملات loaders التي تمكننا من التعامل مع أنواع مختلفة من الملفات وضغطها وتوفيرها في مجلد المشروع النهائي، ونفس الأمر بالنسبة لكود CSS أو SCSS و JavaScript حيث يقوم Webpack بمساعدة babel على سبيل المثال من تحويل كود JavaScript من نسخة حديثة مثل ES6 أو ES7 إلى إصدار أقدم من JavaScript وبالتالي يمكن لمجموعة أكبر من المتصفحات تنفيذ كود JavaScript بدون مشكلة. كما يمكن إستخدام Webpack بملف إعدادات مختلف webpack.config.js لبناء أكثر من نسخة من نفس المشروع، نسخة للتطوير development ونسخة أخرى للنشر production على سبيل المثال. وكل ملخص لما سبق، يقوم Webpack بإستخدام Node.js لعمل الكثير من المهام المعتادة وأتمتتها بسهولة من خلال الكثير من الإضافات plugins والمحملات loaders.1 نقطة
-
بالنسبة للمشكلة الثانية , لاحظ الكود الخاص به <div class="logo-goo">//سوف نعطيه بعض الأصناف <span class="logo mr-auto"></span>//سوف نحذف الصنف mr-auto <i class="fa fa-umbrella-beach fa-3x"></i> </span> <div class="text "> <h2>DIAGOONA</h2> <p>new bootstrap template</p> </div> </div> بعد التعديل يصبح كالتالي <div class="logo-goo d-flex align-items-center"> ^^^^^^^^^^^^^^^^^^^^^^^^^ <span class="logo"></span> <i class="fa fa-umbrella-beach fa-3x"></i> </span> <div class="text "> <h2>DIAGOONA</h2> <p>new bootstrap template</p> </div> </div> سوف يعرض اللوجو بجانب النص أما بالنسبة للكود لا يعمل فهو بسبب أنك لم تقم بتضمين ملف js.js <script src="js/js.js"></script> أرجو منك اضافة السطر , بالنسبة slides.lenght , لاحظ الكود التالي var slides = document.getElementsByClassName("mySlides"); لقد قمنا بجلب جميع العناصر التي لديها الصنف mySlides, نريد ان تقوم بعدهم, نستطيع فعل ذلك كالتالي slides.length حيث أن الخاصية length تقوم بارجاع عدد العناصر في المصفوفة, أما بالنسبة ل n, لاحظ كود جافاسكربت وكود html كود جافاسكربت function showSlides(n) { كود html <span class="dot" onclick="currentSlide(1)"></span> <span class="dot" onclick="currentSlide(2)"></span> <span class="dot" onclick="currentSlide(3)"></span> لاحظ أن الدالة المعرفة في جافاسكربت تستقبل متغير اسمه n , أي عند استدعاءها يجب أن نقوم بتمرير قيمة لها, لاحظ كود html , لقد قمنا باستدعاءها ثلاثة مرات, في كل مرة مررنا قيمة n بقيمة مختلفة , في المرو ألأولى قيمة المتغير n تساوي 1 والمرة الثانية تساوي 2 والمرة الأخيرة والثالثة 3 , ويمكننا استخدام هذه القيمة في الكود الذي ارفقه لك المدرب, سوف تواجهم مشكلة في الكود المرفق وبالتحديد في هذا السطر slides[slideIndex - 1].style.display = "block"; أرجو منك حذفه وتعديل الكود كالآتي function showSlides(n) { var i; var slides = document.getElementsByClassName("mySlides"); // تحديد كامل الشرائح var dots = document.getElementsByClassName("dot"); // تحديد كامل الدوائر if (n > slides.length) { slideIndex = 1 } // تحديد الشريحة الاولى كمفعلة if (n < 1) { slideIndex = slides.length } // تحديد الشريحة الأخيرة كمفعلة for (i = 0; i < slides.length; i++) { slides[i].style.display = "none"; // إخفاء كامل الشرائح if (i+1 == n) { slides[i].style.display = "block"; } } }1 نقطة
-
هناك اختلافات بين هذين الأمرين: بالنسبة لعمليتي الinsert وال update فإن model.save يقوم إما بإدراج أو تحديث كائن في قاعدة بيانات: UPDATE إذا تم تعيين واصفة المفتاح الرئيسي pk للكائن على قيمة يتم تقييمها على أنها True. INSERT إذا لم يتم تعيين واصفة المفتاح الرئيسي للكائن أو إذا لم يحدِّث التحديث أي شيء مثلاً إذا تم تعيين ال pk على قيمة غير موجودة في قاعدة البيانات. بينما model.objects.create تقوم فقط بعملية INSERT. أيضاً إذا تم تعيين واصفة المفتاح الرئيسي على قيمة وكانت موجودة سابقاً، فإن Model.save سينفذ UPDATE، لكن Model.objects.create يعطي IntegrityError. أمثلة: # بفرض كان لدينا نموذج from django.db import models as m class f(m.Model): add = m.DateTimeField(auto_now_add=True) # دعنا نقوم بأخذ غرض من هذا الصف obj = f.objects.create(pk=1) #primary key الآن لو حاولنا إنشاء كائن له نفس ال # سينتج الخطأ التالي ob = f.objects.create(pk=1) # django.db.utils.IntegrityError: (1062, "Duplicate entry '1' for key 'PRIMARY'") ob = f(pk=1).save() # # django.db.utils.IntegrityError: (1048, "Column 'added' cannot be null") ليكن لدينا: class Subject(models.Model): subject_id = models.PositiveIntegerField(primary_key=True, db_column='subject_id') name = models.CharField(max_length=255) max_marks = models.PositiveIntegerField() # Insert/Update #model.save باستخدام #ML ل IT تغيير الاسم من # وتغيير العلامة من 77 ل 89 physics = Subject(subject_id=1, name='IT', max_marks=77) physics.save() math = Subject(subject_id=1, name='ML', max_marks=89) math.save() # النتيجة """ Subject.objects.all().values() <QuerySet [{'subject_id': 1, 'name': 'Math', 'max_marks': 50}]> """ # Model.objects.create # سيعطي خطأ Subject.objects.create(subject_id=1, name='Chemistry', max_marks=100) # IntegrityError: UNIQUE constraint failed: m****t.subject_id أيضاً Model.save تعيد None بيبنما create تعيد package_name.models.Model. ويمكننا أن نقوم بالحفظ من خلال create عن طريق جعله يسلك سلوك Model.save من خلال استخدام force_insert=True أي Model.save(force_insert=True). أي يمكن القول أن Model.objects.create يقوم بتهيئة النموذج ويقوم بالحفظ باستخدام force_insert = True.1 نقطة
-
في البداية عليك أن تتاكد أن عمود التاريخ على هيئة datetime كالتالي: df['date'] = pd.to_datetime(df['date']) بعد ذلك تختار الفترة التي تريد اختيار الصفوف بينها كالتالي: mask = (df['date'] > start_date) & (df['date'] <= end_date) مثال على البيانات الخاصة بك، يمكنك اختبار الكود التالي: import numpy as np import pandas as pd df = pd.DataFrame(np.random.random((200,3))) df['date'] = pd.date_range('2021-1-1', periods=200, freq='D') mask = (df['date'] > '2021-9-1') & (df['date'] <= '2021-9-10') print(df.loc[mask]) ويكون الخرج كالتالي: 0 1 2 date 153 0.208875 0.727656 0.037787 2021-09-02 154 0.750800 0.776498 0.237716 2021-09-03 155 0.812008 0.127338 0.397240 2021-09-04 156 0.639937 0.207359 0.533527 2021-09-05 157 0.416998 0.845658 0.872826 2021-09-06 158 0.440069 0.338690 0.847545 2021-09-07 159 0.202354 0.624833 0.740254 2021-09-08 160 0.465746 0.080888 0.155452 2021-09-09 161 0.858232 0.190321 0.432574 2021-09-10 أو يمكنك الدالة df.loc[start_date:end_date] لاختيار الفترة التي تريدها كالتالي: import numpy as np import pandas as pd df = pd.DataFrame(np.random.random((200,3))) df['date'] = pd.date_range('2021-1-1', periods=200, freq='D') df = df.set_index(['date']) print(df.loc['2021-9-1':'2021-9-10']) ويكون لها نفس الخرج كالدالة السابقة.1 نقطة
-
إضافة للطرق أعلاه.. فلأداء أعلى يفضل استخدام خوارزمية مطابقة السلاسل Jaro-Winkle للقيام بهكذا عمليات، فهي الأفضل من ناحية الأداء والأكثر دقة : import pandas as pd import jellyfish df1 = pd.DataFrame([[1],[2],[3],[4],[5]], index=['one','two','three','four','five'], columns=['number']) df1 """ number one 1 two 2 three 3 four 4 five 5 """ df2 = pd.DataFrame([['a'],['b'],['c'],['d'],['e']], index=['one','too','three','fours','five'], columns=['letter']) df2 """ letter one a too b three c fours d five e """ def get_closest_match(x, list_strings): best_match = None highest_jw = 0 for current_string in list_strings: current_score = jellyfish.jaro_winkler(x, current_string) if(current_score > highest_jw): highest_jw = current_score best_match = current_string return best_match df2.index = df2.index.map(lambda x: get_closest_match(x, df1.index)) df1.join(df2) """ number letter one 1 a two 2 b three 3 c four 4 d five 5 e """1 نقطة
-
هذا الكود البسيط يكفي: df.columns = [''.join(t) for t in df.columns] df أو: df.columns = ['_'.join(tup).rstrip('_') for tup in df.columns.values] df """ USAF WBAN day month s_CDsum s_CLsum s_CNTsum s_PCsum tempfamax tempfamin year 0 702730 26451 1 1 12.0 0.0 13.0 1.0 30.92 24.98 1993 1 702730 26451 2 1 13.0 0.0 13.0 0.0 32.00 24.98 1993 2 702730 26451 3 1 2.0 10.0 13.0 1.0 23.00 6.98 1993 3 702730 26451 4 1 12.0 0.0 13.0 1.0 10.04 3.92 1993 4 702730 26451 5 1 10.0 0.0 13.0 3.0 19.94 10.94 1993 """ أو بالشكل التالي: mi = df.columns #MultiIndex نقوم باستخلاص ال mi """ MultiIndex([( 'USAF', ''), ( 'WBAN', ''), ( 'day', ''), ('month', ''), ( 's_CD', 'sum'), ( 's_CL', 'sum'), ('s_CNT', 'sum'), ( 's_PC', 'sum'), ('tempf', 'amax'), ('tempf', 'amin'), ( 'year', '')], ) """ # نحولها لقائمة mi.tolist() """ [('USAF', ''), ('WBAN', ''), ('day', ''), ('month', ''), ('s_CD', 'sum'), ('s_CL', 'sum'), ('s_CNT', 'sum'), ('s_PC', 'sum'), ('tempf', 'amax'), ('tempf', 'amin'), ('year', '')] """ # نحولها الآن لفهرس ind = pd.Index([e[0] + e[1] for e in mi.tolist()]) ind # نسندها للأعمدة df.columns = ind df """ USAF WBAN day month s_CDsum s_CLsum s_CNTsum s_PCsum tempfamax tempfamin year 0 702730 26451 1 1 12.0 0.0 13.0 1.0 30.92 24.98 1993 1 702730 26451 2 1 13.0 0.0 13.0 0.0 32.00 24.98 1993 2 702730 26451 3 1 2.0 10.0 13.0 1.0 23.00 6.98 1993 3 702730 26451 4 1 12.0 0.0 13.0 1.0 10.04 3.92 1993 4 702730 26451 5 1 10.0 0.0 13.0 3.0 19.94 10.94 1993 """1 نقطة
-
يمكنك استخدام التابع pd.MultiIndex.from_product ك index في dataframe جديد ثم عمل reset لل index كما في المثال التالي a = [1, 2, 3] b = ["a", "b", "c"] index = pd.MultiIndex.from_product([a, b], names = ["a", "b"]) pd.DataFrame(index = index).reset_index() الناتج يكون كالتالي a b 0 1 a 1 1 b 2 1 c 3 2 a 4 2 b 5 2 c 6 3 a 7 3 b 8 3 c1 نقطة
-
بداية من نسخة panda 0.24.0 ، يمكنك استخدام الدالة .to_flat_index والتي تقوم بتنفيذ المطلوب كما في المثال التالي dat = df.loc[:,['name','workshop_period','class_size']].groupby(['name','workshop_period']).describe() print(dat.columns) # MultiIndex(levels=[['class_size'], ['count', 'mean', 'std', 'min', '25%', '50%', '75%', 'max']], # codes=[[0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 2, 3, 4, 5, 6, 7]]) dat.columns = dat.columns.to_flat_index() print(dat.columns) # Index([('class_size', 'count'), ('class_size', 'mean'), # ('class_size', 'std'), ('class_size', 'min'), # ('class_size', '25%'), ('class_size', '50%'), # ('class_size', '75%'), ('class_size', 'max')], # dtype='object') وللفصل بين اسماء الأعمدة يمكنك استخدام الحل التالي dat.columns = ["_".join(a) for a in dat.columns.to_flat_index()]1 نقطة
-
يُعَدّ بناء لغة برمجة خاصة بك أمرًا ليس بالصعب على عكس ما تتوقع الغالبية الساحقة من الناس، خاصةً إن لم ترفع سقف توقعاتك كثيرًا، بل قد يكون فيه كثير من التعلم النافع أيضًا، والذي نريد الإشارة إليه في هذا المقال هو أنّ بناء لغة ليس ضربًا من السحر والشعوذة بسبب شعورنا بالإحساس الذي ينتاب المرء في مثل هذه الحالات، فقد جربناه بأنفسنا مع بعض الاختراعات البشرية التي رأينا فيها ذكاءً وصنعةً جعلتنا نظن أنه يستحيل علينا فهم طريقة عملها وبنائها، لكن القراءة والتجربة تفك كثيرًا من هذا السحر. سنبني في هذا المقال لغة برمجة سنسميها لغة البيض Egg، حيث ستكون صغيرةً وبسيطةً لكنها قوية بما يكفي لتعبِّر عن أيّ حسابات تفكر فيها، كما ستسمح بالتجريدات abstractions البسيطة المبنية على دوال. التحليل إن أول ما تراه عينك عند النظر إلى لغة برمجة هو بنيتها اللغوية syntax أو صيغتها notation، والمحلل parser هو برنامج يقرأ نصًا ما وينتج هيكل بيانات data structure، بحيث يعكس بنية البرنامج الموجود في ذلك النص، فإن لم يشكِّل النص برنامجًا صالحًا، فيجب أن يخبرنا المحلل بالخطأ الذي سبب ذلك. ستكون لغتنا ذات بنية لغوية بسيطة وموحدة، حيث سيكون كل شيء في Egg تعبيرًا، وقد يكون التعبير expresion اسم رابطة binding أو عددًا أو سلسلةً نصيةً string أو حتى تطبيقًا، كما تُستخدَم التطبيقات لاستدعاءات الدوال وللبنى اللغوية مثل if أو while. لن تَدعم السلاسل النصية في Egg أيّ شيء يشبه تهريب الشَرطة المائلة العكسية \، ذلك أنّ السلسلة النصية ببساطة هي سلسلة من محارف داخل اقتباسات مزدوجة، لكن لن تكون هي ذاتها اقتباسات مزدوجة، كما سيكون العدد سلسلةً من الأرقام، ويمكن أن تتكون أسماء الرابطات من أيّ محرف ليس مسافةً فارغةً وليس له معنى خاص في البنية التركيبية للغة. تُكتَب التطبيقات بالطريقة نفسها المكتوبة بها في جافاسكربت، وذلك بوضع أقواس بعد التعبير، ويمكنها امتلاك أيّ عدد من الوسائط arguments بين هذين القوسين مفصول بين كل منها بفاصلة أجنبية ,. do(define(x, 10), if(>(x, 5), print("large"), print("small"))) يعني توحيد لغة Egg أنّ الأشياء التي تُرى على أساس عوامل operators في جافاسكربت -مثل >- هي رابطات عادية في هذه اللغة، وتُطبَّق مثل أيّ دالة أخرى، كما نحتاج إلى بنية do للتعبير عن تنفيذ عدة أشياء في تسلسل واحد، وذلك لعدم وجود مبدأ الكتل blocks في البنية التركيبية للغة. يتكون هيكل البيانات الذي سيستخدمه المحلل لوصف برنامج ما من كائنات تعابير، لكل منها خاصية type توضِّح نوع التعبير وخصائص أخرى تصف محتواه. تمثِّل التعابير التي من النوع "value" سلاسلًا نصيةً مجردةً أو أعدادًا، وتحتوي خاصية value لها على السلسلة النصية أو قيمة العدد الذي تمثله؛ أما التعابير التي من نوع "word" فتُستخدَم للمعرِّفات -أي الأسماء-، فمثل تلك الكائنات لها خاصية name تحمل اسم المعرِّف على أساس سلسلة نصية، وأخيرًا تمثِّل تعابير "apply" التطبيقات، إذ تملك خاصية operator التي تشير مرجعيًا إلى تعبير يُطَبَّق، بالإضافة إلى خاصية args التي تحمل مصفوفةً من تعابير الوسائط argument expressions. سيُمثَّل جزء >(x, 5) من البرنامج السابق كما يلي: { type: "apply", operator: {type: "word", name: ">"}, args: [ {type: "word", name: "x"}, {type: "value", value: 5} ] } تُسمى مثل هذه الهياكل من البيانات باسم شجرة البُنى syntax tree، فإذا تخيلنا الكائنات نقاطًا والروابط التي بينها خطوطًا بين هذه النقاط، فسيكون لدينا شكلًا يشبه الشجرة، فكما أنّ الشجرة بها أغصان تنقسم ويحمل كل منها أغصانًا أخرى؛ فبدوره يشبه احتواء التعابير على تعابير أخرى تحتوي بدورها على تعابير جديدة، وهكذا. هذا على عكس المحلل الذي كتبناه لصيغة ملف الإعدادات في مقال التعابير النمطية Regular Expressions في جافاسكريبت، والذي كانت بنيته بسيطةً نوعًا ما، إذ يُقسِّم الدخل إلى أسطر ويعالج هذه الأسطر واحدًا واحدًا، حيث فلم يكن ممكنًا للسطر الواحد إلا بضع صور بسيطة يمكنه أن يكون عليها؛ أما هنا فيجب إيجاد طريقة أخرى، فالتعابير ليست مقسمةً إلى أسطر، كما تملك بنيةً تعاوديةً recursive، وتحتوي تعابير التطبيقات على تعابير أخرى. يمكن حل هذه المشكلة بسهولة من خلال كتابة دالة محلل تعاودية على النحو الذي يعكس الطبيعة التعاودية للغة. نعرِّف الدالة parseExpression التي تأخذ سلسلةً نصيةً على أساس دخل لها، وتُعيد كائنًا يحتوي هيكل البيانات للتعبير في بداية السلسلة النصية مع الجزء المتبقي من السلسلة النصية بعد تحليل هذا التعبير، ويمكن استدعاء هذه الدالة مرةً أخرى حين نحلل التعابير الفرعية كما في حالة وسيط التطبيق مثلًا، وذلك لنحصل على التعبير الوسيط بالإضافة إلى النص المتبقي، وقد يحتوي هذا النص بدوره على وسائط أخرى، أو قد يكون هو قوس الإغلاق في نهاية قائمة الوسائط. يكون أول جزء في المحلل كالتالي: function parseExpression(program) { program = skipSpace(program); let match, expr; if (match = /^"([^"]*)"/.exec(program)) { expr = {type: "value", value: match[1]}; } else if (match = /^\d+\b/.exec(program)) { expr = {type: "value", value: Number(match[0])}; } else if (match = /^[^\s(),#"]+/.exec(program)) { expr = {type: "word", name: match[0]}; } else { throw new SyntaxError("Unexpected syntax: " + program); } return parseApply(expr, program.slice(match[0].length)); } function skipSpace(string) { let first = string.search(/\S/); if (first == -1) return ""; return string.slice(first); } يجب قص المسافات الفارغة من بداية السلسلة النصية للبرنامج بما أنّ لغة Egg التي نكتبها تشبه جافاسكربت في كونها تسمح لأيّ عدد من المسافات الفارغة بين عناصرها، وهنا يأتي دور دالة skipSpace. تَستخدم parseExpression بعد تخطي أي مسافة بادئة ثلاثة تعبيرات نمطية لتحديد العناصر الصغرى الثلاثة التي تدعمها Egg، وهي السلاسل والأعداد والكلمات، كما يبني المحلل نوعًا مختلفًا من هياكل البيانات وفقًا للتي تطابق منها، فإذا كان الإدخال لا يتطابق مع أحد هذه النماذج الثلاثة، فلا يكون تعبيرًا صالحًا ويرفع المحلل خطأً. نحن نستخدم SyntaxError بدلًا من Error على أساس باني اعتراضات exception، وهو نوع قياسي آخر للأخطاء لأنه أكثر تحديدًا، وهو أيضًا نوع الخطأ الذي يرمى عند محاولة تشغيل برنامج JavaScript غير صالح، ثم نقص الجزء المطابق من سلسلة البرنامج النصية ونمرره مع كائن التعبير إلى parseApply الذي ينظر هل التعبير تطبيق أم لا، فإذا كان تطبيقًا، فسيحلَِل قائمةً من الوسائط محصورةً بين قوسين. function parseApply(expr, program) { program = skipSpace(program); if (program[0] != "(") { return {expr: expr, rest: program}; } program = skipSpace(program.slice(1)); expr = {type: "apply", operator: expr, args: []}; while (program[0] != ")") { let arg = parseExpression(program); expr.args.push(arg.expr); program = skipSpace(arg.rest); if (program[0] == ",") { program = skipSpace(program.slice(1)); } else if (program[0] != ")") { throw new SyntaxError("Expected ',' or ')'"); } } return parseApply(expr, program.slice(1)); } إذا كان المحرف التالي في البرنامج ليس قوسًا بادئًا ) فلن يكون هذا تطبيقًا، وتُعيد parseApply التعبير المعطى لها، وإلا فستتخطى القوس البادئ وتنشئ كائن شجرة بُنى syntax tree object لتعبير التطبيق ذاك، ثم تستدعي parseExpression تعاوديًا لتحلِّل كل وسيط حتى تجد القوس الغالق، كما يكون التعاود هنا غير مباشر من خلال استدعاء parseApply لدالة parseExpression والعكس، ولأن تعبير التطبيق يمكن تطبيقه كما في multiplier(2)(1)، فيجب أن تستدعي parseApply نفسها مرةً أخرى لتنظر فيما إذا كان يوجد زوج آخر من الأقواس أم لا، وذلك بعد تحليل تطبيق ما. هذا كل ما نحتاجه لتحليل لغة Egg، إذ نغلفها في دالة parse لتتحقق أنها وصلت إلى نهاية سلسلة الدخل بعد تحليل التعبير -فبرنامج بلغة Egg هو تعبير وحيد-، ثم تعطينا هيكل البيانات للبرنامج. function parse(program) { let {expr, rest} = parseExpression(program); if (skipSpace(rest).length > 0) { throw new SyntaxError("Unexpected text after program"); } return expr; } console.log(parse("+(a, 10)")); // → {type: "apply", // operator: {type: "word", name: "+"}, // args: [{type: "word", name: "a"}, // {type: "value", value: 10}]} وهكذا تعمل اللغة بنجاح، رغم أنها لا تعطينا معلومات مفيدة حين تفشل أو تتعطل، كما لا تخزِّن السطر والعمود الذي يبدأ عنده كل تعبير -وهو الأمر الذي قد يكون مفيدًا عند الإبلاغ عن الأخطاء فيما بعد-، لكن لا يهم، فما أنجزناه إلى الآن كافي. المقيم لا شك في أننا نريد شجرة بنى لبرنامج ما من أجل تشغيلها، وهذه هي وظيفة المقيِّم evaluator، إذ تعطيه شجرة بنى وكائن نطاق يربط الأسماء بالقيم، وسيقيِّم التعبير الذي تمثله الشجرة، ثم يُعيد القيمة التي يخرجها. const specialForms = Object.create(null); function evaluate(expr, scope) { if (expr.type == "value") { return expr.value; } else if (expr.type == "word") { if (expr.name in scope) { return scope[expr.name]; } else { throw new ReferenceError( `Undefined binding: ${expr.name}`); } } else if (expr.type == "apply") { let {operator, args} = expr; if (operator.type == "word" && operator.name in specialForms) { return specialForms[operator.name](expr.args, scope); } else { let op = evaluate(operator, scope); if (typeof op == "function") { return op(...args.map(arg => evaluate(arg, scope))); } else { throw new TypeError("Applying a non-function."); } } } } يحتوي المقيِّم على شيفرة لكل نوع من أنواع التعابير، ويُخرج لنا تعبير القيمة مصنفة النوع literal value expression قيمته، كما في حالة التعبير 100 الذي يقيِّم إلى العدد 100 فقط؛ أما في حالة الرابطة، فيجب التحقق مما إذا كانت معرَّفةً على الحقيقة في النطاق أم لا، وإن كانت فسنجلب قيمتها. تُعَدّ التطبيقات أكثر تفصيلًا من ذلك، فإذا كانت صيغةً خاصةً مثل if، فلا نقيِّم أيّ شيء ونمرِّر التعابير الوسيطة مع النطاق إلى الدالة التي تعالج هذه الصيغة؛ أما إن كانت استدعاءً عاديًا، فسنقيِّم العامِل ونتحقق أنه دالة، ونستدعيها مع الوسائط المقيَّمة. نستخدِم قيمًا لدوال جافاسكربت عادية لنمثِّل قيم الدوال في Egg، كما سنعود إلى هذا بعد قليل حين تُعرَّف الصيغة الخاصة المسماة fun، ويمثِّل الهيكل التعاودي لـ evaluate هيكلًا مماثلًا للمحلِّل، وكلاهما يعكس هيكل اللغة نفسه، ومن الممكن مكاملة المحلِّل والمقيِّم أثناء التحليل أيضًا، لكن فصلهما عن بعضهما البعض بهذه الطريقة يجعل البرنامج أكثر نقاءً. هذا جل ما نحتاج إليه لتفسير لغة Egg ببساطة، لكن من ناحية أخرى، لا تستطيع فعل الكثير بهذه اللغة دون تعريف بعض الصيغ الخاصة الأخرى وإضافة بعض القيم المفيدة إلى البيئة. الصيغ الخاصة يُستخدَم كائن الصيغ الخاصة specialForms لتعريف البُنى الخاصة في لغة Egg، حيث يربط الكلمات بالدوال التي تقيِّم مثل تلك الصيغ، ولنضف if بما أنه فارغ الآن: specialForms.if = (args, scope) => { if (args.length != 3) { throw new SyntaxError("Wrong number of args to if"); } else if (evaluate(args[0], scope) !== false) { return evaluate(args[1], scope); } else { return evaluate(args[2], scope); } }; تتوقع بنية if ثلاثة وسائط بالضبط، وستقيّم الأول منها، فإذا لم تكن النتيجة هي القيمة false فستقيِّم الثاني، وإلا فالثالث هو الذي يُقيَّم، وتُعَد صيغة if هذه أقرب إلى عامل ?: الثلاثي في جافاسكربت منها إلى عامل if في جافاسكربت أيضًا، فهو تعبير وليس تعليمة، ويُنتِج قيمةً تكون نتيجة الوسيط الثاني أو الثالث. تختلف كذلك لغة Egg عن جافاسكربت في كيفية معالجة القيمة الشرطية إلى if، فهي لا تعامل الصفر والسلسلة النصية الفارغة على أنها خطأ false، بل القيمة false حصرًا وفقط. السبب الذي يجعلنا في حاجة إلى تمثيل if على أساس صيغة خاصة بدلًا من دالة عادية، هو أن جميع وسائط الدوال تُقيَّم قبل استدعاء الدالة، بينما يجب ألا تقيِّم if إلا وسيطها الثاني أو الثالث بناءً على قيمة الوسيط الأول. صيغة while شبيهة بهذا، فبما أن undefined غير موجودة في لغة Egg، فسنُعيد false لعدم وجود نتيجة أفضل وأكثر فائدة، كما في المثال التالي: specialForms.while = (args, scope) => { if (args.length != 2) { throw new SyntaxError("Wrong number of args to while"); } while (evaluate(args[0], scope) !== false) { evaluate(args[1], scope); } return false; }; كذلك لدينا وحدة بنيوية أساسية أخرى هي do التي تنفِّذ كل وسائطها من الأعلى إلى الأسفل، وتكون قيمتها هي القيمة التي ينتجها الوسيط الأخير. specialForms.do = (args, scope) => { let value = false; for (let arg of args) { value = evaluate(arg, scope); } return value; }; ننشئ صيغةً نسميها define كي نستطيع إنشاء رابطات ونعطيها قيمًا جديدةً، حيث تتوقع هذه الصيغة للوسيط الأول لها أن يكون كلمةً وتعبيرًا ينتج القيمة التي سنسدها إلى تلك الكلمة لتكون الوسيط الثاني، وبما أنّ define ما هي إلا تعبير، فيجب أن تُعيد قيمةً ما، وسنجعلها تُعيد القيمة التي أُسندت إليها كما في حالة عامل = في جافاسكربت. specialForms.define = (args, scope) => { if (args.length != 2 || args[0].type != "word") { throw new SyntaxError("Incorrect use of define"); } let value = evaluate(args[1], scope); scope[args[0].name] = value; return value; }; البيئة يكون النطاق الذي تقبَله evaluate كائنًا له خصائص تتوافق أسماؤها مع أسماء الرابطات، كما تتوافق قيمها مع القيم التي ترتبط بهذه الرابطات، وسنعرِّف كائنًا ليمثل النطاق العام. يجب أن تكون لنا وصول إلى قيم بوليانية كي نستطيع استخدام بنية if التي عرفناها لتونا، وبما أنه لا يوجد إلا قيمتان منطقيتان فقط، فلا نحتاج إلى ترميز خاص لهما، بل نربطهما بالقيمتين true وfalse ثم نستخدمهما. const topScope = Object.create(null); topScope.true = true; topScope.false = false; نستطيع الآن تقييم تعبير بسيط يرفض قيمةً بوليانيةً. let prog = parse(`if(true, false, true)`); console.log(evaluate(prog, topScope)); // → false سنضيف بعض قيم الدوال إلى النطاق لتوفير العوامل الحسابية الأساسية وكذلك عوامل الموازنة، كما سنستخدم Function -بهدف تبسيط الشيفرة والحفاظ على قصرها- لتوليف مجموعة من دوال العوامل في حلقة تكرارية بدلًا من تعريف كل واحد منها على حدة. for (let op of ["+", "-", "*", "/", "==", "<", ">"]) { topScope[op] = Function("a, b", `return a ${op} b;`); } إذا كانت لدينا طريقة لإخراج القيم، فسيكون ذلك مفيدًا لنا بلا شك، لذا سنغلِّف console.log في دالة ونسميها print. topScope.print = value => { console.log(value); return value; }; يعطينا هذا الأدوات الأساسية اللازمة لكتابة برامج بسيطة، حيث توفر الدالة أدناه طريقةً سهلةً لتحليل برنامج ما وتشغيله في نطاق جديد: function run(program) { return evaluate(parse(program), Object.create(topScope)); } سنستخدم سلاسل كائن النموذج الأولي لتمثيل النطاقات المتشعِّبة nested scopes كي يتمكن البرنامج من إضافة روابط إلى نطاقه المحلي دون تغيير النطاق الأعلى top-level scope. run(` do(define(total, 0), define(count, 1), while(<(count, 11), do(define(total, +(total, count)), define(count, +(count, 1)))), print(total)) `); // → 55 ذلك هو البرنامج الذي رأيناه عدة مرات من قبل، والذي يحسب مجموع الأرقام من 1 إلى 10 مكتوبًا بلغة Egg، ومن الواضح أنه ليس أجمل من مثيله في جافاسكربت، لكنا نراه ممتازًا إذا نظرنا إلى حقيقة أنّ اللغة التي كُتب بها ليس فيها إلا 150 سطرًا من الشيفرات فقط. الدوال تُعَدّ لغة البرمجة التي ليس فيها دوال لغةً فقيرةً في إمكاناتها، لكن لحسن الحظ فليس من الصعب إضافة بنية مثل fun التي تعامِل وسيطها الأخير على أنه متن الدالة، وستستخدم جميع الوسائط التي قبله على أساس أسماء لمعامِلات الدالة. specialForms.fun = (args, scope) => { if (!args.length) { throw new SyntaxError("Functions need a body"); } let body = args[args.length - 1]; let params = args.slice(0, args.length - 1).map(expr => { if (expr.type != "word") { throw new SyntaxError("Parameter names must be words"); } return expr.name; }); return function() { if (arguments.length != params.length) { throw new TypeError("Wrong number of arguments"); } let localScope = Object.create(scope); for (let i = 0; i < arguments.length; i++) { localScope[params[i]] = arguments[i]; } return evaluate(body, localScope); }; }; تحصل الدوال في لغة Egg على نطاقاتها المحلية الخاصة بها، إذ تُنشِئ الدالة المنتَجة بواسطة صيغة fun هذا النطاق المحلي، وتضيف الرابطات الوسيطة إليه، ثم تقيِّم متن الدالة في هذا النطاق وتُعيد النتيجة. run(` do(define(plusOne, fun(a, +(a, 1))), print(plusOne(10))) `); // → 11 run(` do(define(pow, fun(base, exp, if(==(exp, 0), 1, *(base, pow(base, -(exp, 1)))))), print(pow(2, 10))) `); // → 1024 التصريف يسمى الذي بنيناه حتى الآن بالمفسِّر interpreter، والذي يتصرف مباشرةً أثناء التقييم على تمثيل البرنامج الذي أنتجه المحلِّل؛ أما التصريف compilation، فهو عملية إضافة خطوة أخرى بين التحليل وتشغيل البرنامج، إذ تحوِّل البرنامج إلى شيء يمكن تقييمه بكفاءة أكبر من خلال إضافة كل ما يمكن إضافته من عمل ومهام مقدمًا، فمن الواضح في اللغات متقَنة التصميم مثلًا استخدام كل رابطة وأيّ رابطة مشار إليها بدون تشغيل البرنامج فعليًا، حيث يُستخدَم هذا لتجنب البحث عن الرابطة باسمها في كل مرة يوصَل إليها، بدلًا من جلبها مباشرةً من موقع محدد سلفًا في الذاكرة. يتضمن التصريف عادةً تحويل البرنامج إلى لغة الآلة، وهي الصيغة الخام التي يستطيع معالج الحاسوب تنفيذها، لكن هذه ليست الصورة الوحيدة له، فأيّ عملية تحوِّل البرنامج إلى تمثيل آخر مختلف يمكن النظر إليها على أنها تصريف كذلك. سيكون من الممكن كتابة خطة تقييم بديلة للغة Egg، إذ تبدأ بتحويل البرنامج إلى برنامج جافاسكربت أولًا، ثم تستخدِم Function لاستدعاء مصرِّف جافاسكربت له، وبعدها سنحصل على النتيجة، فإذا كان هذا بكفاءة، فسيجعل لغة Egg تعمل بمعدل سريع جدًا مع الحفاظ على بساطة الاستخدام. الاحتيال لعلك لاحظت حين عرَّفنا if وwhile على أنهما ليستا سوى تغليف بسيط نوعًا ما حول نظيرتيهما في جافاسكربت، وبالمثل، فإنّ القيم في Egg ما هي إلا قيم جافاسكربت العادية. إذا وازنت استخدام Egg المبني على جافاسكربت مع كمية الجهد والتعقيد المطلوب لبناء لغة برمجة من الوظائف المجردة الخام التي يوفرها الحاسوب على أساس عتاد، فإنّ الفارق عظيم، وعلى كل حال يعطيك هذا المثال صورةً للطريقة التي تعمل بها لغة البرمجة. إذا وضعنا هذا في ميزان الإنجاز، فستكون الاستفادة من العجلة الموجودة أفضل من إعادة اختراعها وتنفيذ كل شيء بأنفسنا، رغم أنّ هذه اللغة التي أنشأناها في هذا المقال والتي تشبه لعب الأطفال لا تفعل أي شيء لا تفعله جافاسكربت بالكفاءة نفسها إن لم يكن أفضل، إلا أن هناك حالات سيكون من المفيد فيها كتابة برامج بسيطة لإنجاز المهام التي بين أيدينا، ومثل هذه اللغة ليس عليها أن تكون على صورة اللغة التقليدية، فإذا لم تأتي جافاسكربت بتعابير نمطية مثلًا، فستستطيع كتابة محلِّل خاص بك ومقيِّم كذلك من أجل هذه التعابير؛ أو لنقل أنك تبني ديناصورًا آليًا عملاقًا وتريد برمجة سلوكه، فقد لا تكون جافاسكربت حينها هي اللغة المثلى لذلك، وستجد أنك تحتاج إلى لغة تبدو هكذا: behavior walk perform when destination ahead actions move left-foot move right-foot behavior attack perform when Godzilla in-view actions fire laser-eyes launch arm-rockets يُطلَق على مثل هذه اللغة أنها لغة مختصة بمجال بعينه domain-specific، وهي لغة مفصَّلة لتعبِّر عن عناصر مجال معين من المعرفة، ولا تتعداه إلى غيره، كما تكون أكثر وصفًا وإفصاحًا عن اللغة الموجَّهة للأغراض العامة لأنها مصمَّمة لتصف الأشياء المراد وصفها حصرًا في هذا المجال وحسب. تدريبات المصفوفات اجعل لغة Egg تدعم المصفوفات من خلال إضافة الدوال الثلاثة التالية إلى النطاق العلوي top scope: array(...values) لبناء مصفوفة تحتوي على قيم وسيطة. length(array) للحصول على طول مصفوفة ما. element(array, n) لجلب العنصر رقم n من مصفوفة ما. تستطيع تعديل شيفرة التدريب لكتابة الحل وتشغيلها في طرفية المتصفح إن كنت تقرأ من متصفح، أو بنسخها إلى codepen. // عدِّل هذه التعريفات... topScope.array = "..."; topScope.length = "..."; topScope.element = "..."; run(` do(define(sum, fun(array, do(define(i, 0), define(sum, 0), while(<(i, length(array)), do(define(sum, +(sum, element(array, i))), define(i, +(i, 1)))), sum))), print(sum(array(1, 2, 3)))) `); // → 6 إرشادات للحل إن أسهل طريقة لإضافة الدعم هي تمثيل مصفوفات Egg بمصفوفات جافاسكربت، ويجب أن تكون القيم المضافة إلى النطاق العلوي دوالًا، كما يمكن أن يكون تعريف array بسيطًا جدًا إذا استَخدَمت وسيط rest مع الصيغة ثلاثية النقاط triple-dot notation. التغليف Closure تسمح لنا الطريقة التي عرَّفنا بها fun بإضافة دوال في Egg للإشارة مرجعيًا إلى النطاق المحيط، مما يسمح لمتن الدالة أن تستخدِم قيمًا محليةً كانت مرئيةً في وقت تعريف الدالة، تمامًا مثلما تفعل دوال جافاسكربت، ويوضِّح البرنامج التالي هذا، إذ تُعيد دالة f دالةً تضيف وسيطها إلى وسيط f، مما يعني أنها تحتاج إلى وصول للنطاق المحلي الموجود داخل f كي تستطيع استخدام الرابطة a. تستطيع تعديل شيفرة التدريب لكتابة الحل وتشغيلها في طرفية المتصفح إن كنت تقرأ من متصفح، أو بنسخها إلى codepen. run(` do(define(f, fun(a, fun(b, +(a, b)))), print(f(4)(5))) `); // → 9 ارجع الآن إلى تعريف صيغة fun واشرح الآلية المسببة لعملها. إرشادات للحل سنستخدِم آليات جافاسكربت مرةً أخرى للحصول على مزايا مشابهة في Egg، حيث تُمرَّر الصيغ الخاصة إلى النطاق المحلي الذي تقيَّم فيه كي تقيِّم هي صيغها الفرعية في ذلك النطاق، ويكون للدالة التي تعيدها fun وصول إلى وسيط scope المعطى للدالة المغلِّفة، كما تستخدِم ذلك لإنشاء نطاق الدالة المحلي حين تُستدعى. يعني هذا أن النموذج الأولي للنطاق المحلي سيكون هو النطاق الذي أُنشَئت فيه الدالة مما يمكننا من الوصول إلى الرابطات التي في ذلك النطاق من خلال الدالة، وهذا كله من أجل استخدام التغليف closure رغم أنك في حاجة إلى مزيد من العمل لتُصرِّف ذلك بكفاءة. التعليقات أليس من الجميل أن تتمكن من كتابة تعليقات في لغة Egg؟ فلو جعلنا التعليق يبدأ بعلامة # مثلًا كما في حال علامتي // في جافاسكربت -ولا تقلق بشأن المحلِّل، إذ لن نجري أيّ تغييرات جوهرية فيه كي يدعم التعليقات-، فما علينا سوى تغيير skipspace كي تتخطى التعليقات كذلك، كما لو كانت مسافات فارغة، بحيث نتخطى التعليقات في كل مرة نستدعي فيها skipspace. الشيفرة أدناه تمثل skipspace، عدِّلها لتضيف دعم التعليقات في لغة Egg، مسترشدًا بما سبق. تستطيع تعديل شيفرة التدريب لكتابة الحل وتشغيلها في طرفية المتصفح إن كنت تقرأ من متصفح، أو بنسخها إلى codepen. function skipSpace(string) { let first = string.search(/\S/); if (first == -1) return ""; return string.slice(first); } console.log(parse("# hello\nx")); // → {type: "word", name: "x"} console.log(parse("a # one\n # two\n()")); // → {type: "apply", // operator: {type: "word", name: "a"}, // args: []} إرشادات للحل تأكد من جعل حلّك قادرًا على معالجة التعليقات المتعددة في صف مع مسافات فارغة محتملة بينها أو بعدها. سيكون التعبير النمطي أسهل طريقة تستخدمها في هذا التمرين للحل، لهذا اكتب شيئًا يطابق "مسافةً فارغةً أو تعليقًا أو صفرًا أو أكثر من مرة". واستخدم التابع exec أوmatch، وانظر إلى طول أول عنصر في المصفوفة المعادة -أي التطابق الكامل- لتعرف كم عدد المحارف التي عليك قصها. إيجاد النطاق الطريقة الوحيدة حاليًا لإسناد قيمة إلى رابطة هي define، حيث تتصرف هذه البنية مثل طريقة لتعريف رابطات جديدة وإعطاء قيمة جديدة للرابطات الحالية. لكن هذا الإبهام يجعلك تقع في مشكلة تعريف رابطة محلية بالاسم نفسه في كل مرة تحاول إعطاء رابطة غير محلية قيمةً جديدةً، كما نستنكر هذه الطريقة في معالجة النطاقات رغم وجود لغات مصممة أصلًا على هذا الأساس. أضف صيغة set الخاصة التي تشبه define، وتعطي قيمةً جديدةً للرابطة لتحدِّث الرابطة في نطاق خارجي إذا لم تكن موجودةً سلفًا في النطاق الداخلي، وإن لم تكن هذه الرابطة معرفةً، فأبلغ بالخطأ ReferenceError الذي هو نوع خطأ قياسي. سيعيقك نوعًا ما أسلوب تمثيل النطاقات على أساس كائنات بسيطة من أجل السهولة ها هنا، خاصةً إذا أردت استخدام دالة Object.getPrototypeOf مثلًا التي تعيد النموذج الأولي لكائن ما، وتذكَّر أيضًا أنّ النطاقات لا تنحدر من Object.prototype، لذا فإن أردت استدعاء hasOWnProperty عليها، فعليك استخدام التعبير التالي: Object.prototype.hasOwnProperty.call(scope, name); specialForms.set = (args, scope) => { // ضع شيفرتك هنا. }; run(` do(define(x, 4), define(setx, fun(val, set(x, val))), setx(50), print(x)) `); // → 50 run(`set(quux, true)`); // → ReferenceError أحد صور تستطيع تعديل شيفرة التدريب لكتابة الحل وتشغيلها في طرفية المتصفح إن كنت تقرأ من متصفح، أو بنسخها إلى codepen. إرشادات للحل سيكون عليك التكرار على نطاق واحد في كل مرة باستخدام Object.getPrototypeOf للذهاب إلى النطاق الخارجي اللاحق. واستخدِم hasOwnProperty لتعرف ما إذا كانت الرابطة الموضَّحة بخاصية name في أول وسيط لـ set موجودةً في ذلك النطاق أم لا، فإن كانت كذلك فاضبطها على نتيجة تقييم الوسيط الثاني لـ set ثم أعد تلك القيمة، وإذا وصلت إلى أقصى نطاق خارجي -بحيث تكون إعادة Object.getPrototypeOf هي null- ولم تعثر على الرابطة بعد، فستكون هذه الرابطة غير موجودة ويجب رمي خطأ هنا. ترجمة -بتصرف- للفصل الثاني عشر من كتاب Elequent Javascript لصاحبه Marijn Haverbeke. اقرأ أيضًا المقال السابق: البرمجة غير المتزامنة في جافاسكريبت دليلك الشامل لتعلم البرمجة النسخة الكامة من كتاب مدخل إلى الذكاء الاصطناعي وتعلم الآلة1 نقطة
-
أيضاً من خلال استخدام الدالة apply كالتالي، وهي الطريقة الأبسط: import pandas as pd df = pd.DataFrame({'Year': ['1', '1','2','2'], 'month': ['june', 'july','june','july']}) df """ Year month 0 1 june 1 1 july 2 2 june 3 2 july """ df.groupby(["Year"])["month"].apply('-'.join) """ Year 1 june-july 2 june-july Name: month, dtype: object """ أو عن طريق استخدام lambda مع الدالة agg كالتالي: df.groupby('Year').agg(lambda x : '-'.join(set(x))) """ month Year 1 july-june 2 july-june """1 نقطة
-
في pandas النسخة بداية من 1.2 أو أحدث، يمكنك استخدام الدالة merge مباشرة حيث توفر تلك الخاصية كالتالي: from pandas import DataFrame df1 = DataFrame({'col1':[a,b],'col2':[c,d]}) df2 = DataFrame({'col3':[e,f]}) df1.merge(df2, how='cross') أما في النسخ الأقدم فيجب تعريف الضرب بشكل خاص كما نفعل في الضرب في SQL بحيث نقوم بعملية الضرب على المفتاح key الذي يجب أن يكون متشابها بين الأعمدة كالتالي: from pandas import DataFrame, merge df1 = DataFrame({'key':[1,1], 'col1':[a,b],'col2':[c,d]}) df2 = DataFrame({'key':[1,1], 'col3':[e,f]}) merge(df1, df2,on='key')[['col1', 'col2', 'col3']] وفي الحالتين يكون الخرج كالتالي: col1 col2 col3 0 a c e 1 a c f 2 b d e 3 b d f1 نقطة
-
يمكنك استخدام الدالة get_close_matches للمقارنة بين العناصر وربط العناصر المتشابهة سويا ثم استخدام الدالة join لجمعهم سويا مثل الكود التالي: In [1]: import difflib In [2]: difflib.get_close_matches Out[3]: <function difflib.get_close_matches> In [4]: df2.index = df2.index.map(lambda x: difflib.get_close_matches(x, df1.index)[0]) In [5]: df2 Out[5]: letter one a two b three c four d five e In [6]: df1.join(df2) Out[6]: number letter one 10 a two 20 b three 30 c four 40 d five 50 e كذلك يمكنك استخدام الدالة merge اذا كانت الdataframes علي هيئة أعمدة كالتالي: df1 = DataFrame([[10,'one'],[20,'two'],[30,'three'],[40,'four'],[50,'five']], columns=['number', 'name']) df2 = DataFrame([['a','one'],['b','two'],['c','three'],['d','four'],['e','five']], columns=['letter', 'name']) df2['name'] = df2['name'].apply(lambda x: difflib.get_close_matches(x, df1['name'])[0]) df1.merge(df2) أو استخدام المكتبة fuzzywuzzy لجمعهم سويا كالتالي: from fuzzywuzzy import fuzz from fuzzywuzzy import process fuzzy_merge(df1, df2, 'index', 'index', threshold=80)1 نقطة
-
يمكنك أيضاً استخدام الدالة notnull ببساطة كالتالي import pandas as pd df = df[pd.notnull(df['value'])] أو يمكنك عكس الدالة isnull كالتالي df[~df.value.isnull()] أو isnan df[~np.isnan(df.value)]1 نقطة
-
هناك عدة طرق للقيام بهذا، مثلا يمكنك فقط الابقاء على الصفوف التي تحتوى على قيم بدلا من إزالة الصفوف التي تحتوى على NaN كالتالي: df = df[df['value'].notna()] أو يمكنك إزالة الصفوف التي تحتوى على قيم NaN كالتالي: df.dropna(subset=['value']) اما اذا أردت ازالة الصف اذا كان كل قيم أعمدته ب NaN يمكنك استخدام الكود التالي: df.dropna(how='all')1 نقطة
-
هذا من الأسباب التي أدت لظهور شيء مثل nextjs واذا أردت كل ميزات ال seo فيمكنك أن تحول التطبيق الى nextjs وستتمتع هناك بكل ميزات ال seo اذا كان هذا يعتبر خيار مكلفا لك فيمكنك استخدام الخيار الثاني وهو انشاء custom server و عمل الserver side rendering بنفسك و ايتاح react app عن طريق server ةهذا مثال ملائم جدا في حالتك أولا ضع placeholders في index.html داخل مجلد public <head> ... <meta name="description" content="__META_DESCRIPTION__"/> <meta name="og:title" content="__META_OG_TITLE__"/> <meta name="og:description" content="__META_OG_DESCRIPTION__"/> <meta name="og:image" content="__META_OG_IMAGE__"/> ... </head> ثم ستملأ ال placeholders في ال custom server وهكذا حلت مشكلتك كليا const path = require('path'); const fs = require("fs"); const app = express(); const PORT = process.env.PORT || 3000; const indexPath = path.resolve(__dirname, '..', 'build', 'index.html'); // ايتاح المصادر الثابتة app.use(express.static( path.resolve(__dirname, '..', 'build'), { maxAge: '30d' }, )); app.get('/*', (req, res, next) => { fs.readFile(indexPath, 'utf8', (err, htmlData) => { if (err) { console.error('Error during file reading', err); return res.status(404).end() } // المعرف من الرابط مثلا const postId = req.query.id; const post = axios(....postId);//هذا لجلب المعلومات if(!post) return res.status(404).send("Post not found"); // inject meta tags htmlData = htmlData.replace( "<title>React App</title>", `<title>${post.title}</title>` ) .replace('__META_OG_TITLE__', post.title) .replace('__META_OG_DESCRIPTION__', post.description) .replace('__META_DESCRIPTION__', post.description) .replace('__META_OG_IMAGE__', post.thumbnail) return res.send(htmlData); }); }); // listening... app.listen(PORT, (error) => { if (error) { return console.log('Error during app startup', error); } console.log("listening on " + PORT + "..."); });1 نقطة
-
بشكل إفتراضي يتم تخزين السجلات logs في نظام Linux في أحد المسارات التالية (حسب بنية النظام لديك): /var/log/nginx/nginx_error.log /var/log/nginx/error.log يمكنك عرض آخر جزء من السجل من خلال أمر tail، كالتالي: tail -f /var/log/nginx/error.log لاحظ: يجب تغير المسار في الأمر السابق حسب المسار الذي لديك أما في MacOS فالمسار مختلف وهو: /usr/local/var/log/nginx أما في Windows فيختلف المسار حسب مكان تثبيت الخادم لكن يمكنك الوصول من خلال تنفيذ الأمر التالي: nginx -s reopen أما إن أردت أن يقوم Django بحفظ السجلات فيجب عليك أن تقوم بتعديل ملف settings.py لشمل الكود كالتالي: LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'file': { 'level': 'DEBUG', 'class': 'logging.FileHandler', 'filename': os.path.join(BASE_DIR, 'debug.log'), }, }, 'loggers': { 'django': { 'handlers': ['file'], 'level': 'DEBUG', 'propagate': True, }, }, }1 نقطة
-
السلام عليكم أخي هناك دورات أكاديمية مجانية كثيرة في اليوتيوب يمكنك الإعتماد عليها في تطوير مهاراتك وهناك أيضا موقع إدراك فهو مجاني ويعطيك شهادة بعد إكمال الدورة إذا تريد تطوير مهارتك يجب عليك التطبيق كثيرا والقيام بالتغذية البصرية وحاول أن تخرج بستايل خاص بك تحياتي1 نقطة